summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/ChangeLog.tree-ssa566
-rw-r--r--gcc/cp/Make-lang.in14
-rw-r--r--gcc/cp/call.c20
-rw-r--r--gcc/cp/class.c31
-rw-r--r--gcc/cp/cp-lang.c121
-rw-r--r--gcc/cp/cp-mudflap.c108
-rw-r--r--gcc/cp/cp-simplify.c236
-rw-r--r--gcc/cp/cp-tree.def9
-rw-r--r--gcc/cp/cp-tree.h19
-rw-r--r--gcc/cp/cvt.c5
-rw-r--r--gcc/cp/decl.c89
-rw-r--r--gcc/cp/decl2.c17
-rw-r--r--gcc/cp/error.c12
-rw-r--r--gcc/cp/except.c110
-rw-r--r--gcc/cp/expr.c18
-rw-r--r--gcc/cp/init.c137
-rw-r--r--gcc/cp/name-lookup.h1
-rw-r--r--gcc/cp/optimize.c5
-rw-r--r--gcc/cp/parser.c22
-rw-r--r--gcc/cp/pt.c37
-rw-r--r--gcc/cp/rtti.c23
-rw-r--r--gcc/cp/semantics.c220
-rw-r--r--gcc/cp/tree.c131
-rw-r--r--gcc/cp/typeck.c67
-rw-r--r--gcc/cp/typeck2.c9
26 files changed, 1456 insertions, 584 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 27fc85f79ec..9d990ee3642 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+2004-05-13 Diego Novillo <dnovillo@redhat.com>
+
+ Merge from tree-ssa-20020619-branch. See
+ ChangeLog.tree-ssa for details.
+
+ * Make-lang.in, call.c, class.c, cp-lang.c, cp-tree.def,
+ cp-tree.h, cvt.c, decl.c, decl2.c, error.c, except.c,
+ expr.c, init.c, name-lookup.h, optimize.c, parser.c,
+ pt.c, rtti.c, semantics.c, tree.c, typeck.c, typeck2.c:
+ Merged.
+ * cp-mudflap.c: New file.
+ * cp-simplify.c:: New file.
+
2004-05-03 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/14389
diff --git a/gcc/cp/ChangeLog.tree-ssa b/gcc/cp/ChangeLog.tree-ssa
new file mode 100644
index 00000000000..a52dea67450
--- /dev/null
+++ b/gcc/cp/ChangeLog.tree-ssa
@@ -0,0 +1,566 @@
+2004-04-19 Richard Henderson <rth@redhat.com>
+
+ * except.c (check_handlers_1): Use locus stored in master for warning.
+ * tree.c (cp_walk_subtrees): Save and restore input_location.
+
+2004-04-12 Diego Novillo <dnovillo@redhat.com>
+
+ * cp-lang.c (LANG_HOOKS_RTL_EXPAND_START): Remove.
+ (LANG_HOOKS_RTL_EXPAND_STMT): Remove.
+ * semantics.c (cxx_expand_function_start): Remove.
+
+2004-04-12 Richard Henderson <rth@redhat.com>
+
+ * except.c (check_handlers_1): Use EXPR_LOCUS instead of STMT_LINENO.
+ * semantics.c (finalize_nrv_r): Likewise.
+ * tree.c (cp_walk_subtrees): Likewise.
+ * parser.c (cp_parser_statement): Save and restore entire locus;
+ set EXPR_LOCUS.
+ * pt.c (tsubst_expr): Don't special-case LABEL_STMT.
+
+2004-04-01 Diego Novillo <dnovillo@redhat.com>
+
+ * name-lookup.c (innermost_nonclass_level): Check for
+ error_mark_node.
+
+2004-03-25 Diego Novillo <dnovillo@redhat.com>
+
+ * parser.c (cp_parser_class_specifier): Initialize
+ variable 'attributes'.
+
+2004-03-17 Richard Henderson <rth@redhat.com>
+
+ * cp-lang.c (cxx_types_compatible_p): Use
+ same_type_ignoring_top_level_qualifiers_p.
+
+2004-03-16 Dale Johannesen <dalej@apple.com>
+
+ * cp-lang.c (cxx_types_compatible_p): New.
+ LANG_HOOKS_TYPES_COMPATIBLE_P: New.
+
+2004-03-10 Jason Merrill <jason@redhat.com>
+
+ PR c++/14452
+ * tree.c (stabilize_init): Return whether or not it worked.
+ * init.c (build_new_1): If not, use a sentry.
+ * cp-tree.h: Adjust prototype.
+
+2004-03-01 Jeff Law <law@redhat.com>
+
+ * init.c (build_vec_delete_1): Convert 2nd argument to NE_EXPR to
+ the proper type.
+
+2004-02-24 Jason Merrill <jason@redhat.com>
+
+ PR c++/13944
+ * except.c (do_free_exception): Remove #if 0 wrapper.
+ (build_throw): Use it if we elide a copy into the exception object.
+
+ * tree.c (stabilize_call): Fix thinko.
+
+2004-02-19 Steven Bosscher <stevenb@suse.de>
+
+ * decl.c (poplevel): Don't output nested inline functions.
+
+2004-02-16 Richard Henderson <rth@redhat.com>
+
+ * call.c (build_call, build_over_call, build_new_method_call): Add
+ static chain operand to call_expr.
+ * decl.c (build_offset_ref_call_from_tree): Likewise.
+ * parser.c (cp_parser_postfix_expression): Likewise.
+ * semantics.c (finish_call_expr): Likewise.
+ * cp-lang.c (cp_expand_decl): Don't declare_nonlocal_label.
+
+2004-02-09 Richard Henderson <rth@redhat.com>
+
+ * cp-lang.c (LANG_HOOKS_FUNCTION_MISSING_NORETURN_OK_P): New.
+ * cp-tree.h (cp_missing_noreturn_ok_p): Declare.
+ * decl.c (cp_missing_noreturn_ok_p): Export.
+ (cxx_init_decl_processing): Don't set lang_missing_noreturn_ok_p.
+
+2004-02-06 Andrew Pinski <pinskia@physics.uc.edu>
+
+ PR c/13863
+ * cp-lang.c (LANG_HOOKS_DECL_UNINIT): Remove.
+
+2004-02-03 Richard Henderson <rth@redhat.com>
+
+ PR middle-end/13325
+ * call.c, cvt.c, init.c, typeck.c: Use TREE_NO_WARNING instead
+ of TREE_NO_UNUSED_WARNING.
+ * cvt.c (convert_to_void): Also use it for "has no effect" warning.
+
+2004-01-30 Frank Ch. Eigler <fche@redhat.com>
+
+ * cp-mudflap.c (mflang_flush_calls): Mark static ctor as TREE_USED.
+
+2004-01-12 Jason Merrill <jason@redhat.com>
+
+ * cp-lang.c (ok_to_generate_alias_set_for_type): Remove.
+ (cxx_get_alias_set): Allow all types.
+
+2004-01-08 Frank Ch. Eigler <fche@redhat.com>
+
+ * cp-mudflap.c (mflang_flush_calls): mf_mark synthetic function.
+
+2004-01-04 Richard Henderson <rth@redhat.com>
+
+ * call.c (build_over_call): Don't create a save_expr of an
+ aggregate, but rather its address.
+
+2004-01-01 Richard Henderson <rth@redhat.com>
+
+ * expr.c (cxx_expand_expr): Don't handle THROW_EXPR, or
+ MUST_NOT_THROW_EXPR.
+ * semantics.c (genrtl_try_block, genrtl_eh_spec_block,
+ genrtl_handler, cp_expand_stmt): Remove.
+ (init_cp_semantics): Don't set lang_expand_stmt.
+
+2003-12-31 Richard Henderson <rth@redhat.com>
+
+ * cp-mudflap.c (mflang_register_call): Remove.
+
+2003-12-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/12453
+ * cp-simplify.c (cp_gimplify_init_expr): Look inside STMT_EXPRs
+ and COMPOUND_EXPRs to find an AGGR_INIT_EXPR.
+
+2003-12-16 Jason Merrill <jason@redhat.com>
+
+ PR middle-end/12920
+ * decl.c (grokdeclarator): Immediately layout an
+ ARRAY_TYPE used in a pointer-to-array declarator.
+
+2003-12-16 Jan Hubicka <jh@suse.cz>
+
+ Revert until initializers are made language independent:
+ * cp-lang.c (LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR): Kill.
+ * cp-tree.h (cxx_callgraph_analyze_expr): Kill.
+ * decl2.c (cxx_callgraph_analyze_expr): Kill.
+
+2003-12-14 Jan Hubicka <jh@suse.cz>
+
+ * cp-lang.c (LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR): Kill.
+ * cp-tree.h (cxx_callgraph_analyze_expr): Kill.
+ * decl2.c (cxx_callgraph_analyze_expr): Kill.
+
+2003-11-24 Richard Henderson <rth@redhat.com>
+
+ * Make-lang.in (tree.o, typeck.o): Remove -Wno-error.
+
+2003-11-20 Richard Henderson <rth@redhat.com>
+
+ * call.c (build_java_interface_fn_ref): Use build_address+convert.
+ * except.c (build_eh_type_type): Likewise.
+ * class.c (build_base_path): Use convert+build_indirect_ref.
+ * init.c (expand_virtual_init): Likewise.
+ * rtti.c (get_tinfo_decl_dynamic): Use convert.
+
+2003-11-20 Frank Ch. Eigler <fche@redhat.com>
+
+ * cp-mudflap.c (mflang_flush_calls): Adapt to direct expansion of
+ synthetic function, bypassing callgraph code.
+ * cp-decl2.c (finish_file): Call mudflap after callgraph-based
+ expansion.
+
+2003-11-17 Jason Merrill <jason@redhat.com>
+
+ * init.c (build_new_1): Preevaluate initializer. Simplify EH code.
+ (build_init): Call a constructor rather than call build_aggr_init
+ for classes.
+ * except.c (stabilize_throw_expr): Remove.
+ (build_throw): Use stabilize_init instead of stabilize_throw_expr.
+ * tree.c (stabilize_call, stabilize_init): New fns.
+ * call.c (build_over_call): A constructor no longer returns the
+ address of the object.
+
+2003-11-16 Richard Henderson <rth@redhat.com>
+
+ * typeck.c (pointer_diff): Remove unused variable.
+
+2003-11-16 Jason Merrill <jason@redhat.com>
+
+ PR optimization/11269
+ * semantics.c (finalize_nrv_r): Rename from nullify_returns_r.
+ Also replace uses of the nrv with our RESULT_DECL.
+ (cxx_expand_function_start): Don't mess with the nrv.
+ (finalize_nrv): New fn.
+ * cp-tree.h: Declare it.
+ * decl.c (finish_function): Call it.
+ * tree.c (cp_copy_res_decl_for_inlining): Don't mess with the nrv.
+
+2003-11-10 Richard Henderson <rth@redhat.com>
+
+ * cp-simplify.c (gimplify_must_not_throw_expr): Replace add_tree
+ with append_to_statement_list.
+
+2003-10-30 Richard Henderson <rth@redhat.com>
+
+ * decl.c (pop_switch): Call c_do_switch_warnings.
+
+2003-10-23 Richard Henderson <rth@redhat.com>
+
+ * cp-simplify.c (cp_gimplify_expr): Return gimplify_status.
+
+2003-10-16 Richard Henderson <rth@redhat.com>
+
+ * decl.c (finish_function): Don't check flag_disable_gimple.
+
+2003-10-14 Richard Henderson <rth@redhat.com>
+
+ * decl.c (finish_function): Always gimplify; call c_warn_unused_result.
+
+2003-10-13 Richard Henderson <rth@redhat.com>
+
+ * pt.c (push_tinst_level): Use annotate_with_locus.
+
+2003-10-12 Richard Henderson <rth@redhat.com>
+
+ * call.c (call_builtin_trap): Use implicit_built_in_decls.
+ * class.c (build_base_path): Set TREE_INVARIANT.
+ (build_vtbl_ref_1, build_vtbl_initializer): Likewise.
+ * decl.c (build_enumerator): Likewise.
+ * init.c (build_zero_init): Likewise.
+ * pt.c (push_inline_template_parms_recursive): Likewise.
+ (build_template_parm_index, reduce_template_parm_level): Likewise.
+ (process_template_parm): Likewise.
+ * rtti.c (tinfo_base_init, generic_initializer): Likewise.
+ (ptr_initializer, ptm_initializer, class_initializer): Likewise.
+ * typeck.c (build_ptrmemfunc1): Likewise.
+ * typeck2.c (process_init_constructor): Likewise.
+
+ * calls.c (dfs_accumulate_vtbl_inits): Rely on build to set
+ TREE_CONSTANT.
+ (build_vtbl_initializer): Likewise.
+ * init.c (build_vtbl_address): Likewise.
+ * rtti.c (tinfo_base_init): Likewise.
+ * tree.c (make_ptrmem_cst): Likewise.
+ * typeck.c (decay_conversion): Likewise.
+ (get_member_function_from_ptrfunc, build_binary_op): Likewise.
+ (pointer_diff, build_address, build_nop, build_unary_op): Likewise.
+
+2003-09-30 Richard Henderson <rth@redhat.com>
+
+ * decl.c (finish_function): Set cfun->function_end_locus.
+
+2003-09-24 Jason Merrill <jason@redhat.com>
+
+ * class.c, decl.c, decl2.c, error.c, init.c, lex.c, method.c,
+ pt.c, semantics.c, tree.c: Revert from TREE_LOCUS to
+ DECL_SOURCE_LOCATION.
+
+2003-09-17 Richard Henderson <rth@redhat.com>
+
+ * decl.c (cxx_init_decl_processing): Don't using_eh_for_cleanups
+ if exceptions are disabled.
+
+2003-09-03 Richard Henderson <rth@redhat.com>
+
+ * cp-lang.c (LANG_HOOKS_RTL_EXPAND_STMT): Use expand_stmt_toplev.
+
+2003-09-03 Richard Henderson <rth@redhat.com>
+
+ * decl.c (finish_function): Fix misapplied patch. Don't
+ free_after_parsing or free_after_compilation. For real this time.
+
+2003-08-22 Jason Merrill <jason@redhat.com>
+
+ * cp-simplify.c (cp_gimplify_init_expr): Update use of predicates.
+
+2003-08-21 Jason Merrill <jason@redhat.com>
+
+ * cp-simplify.c (cp_gimplify_expr): Use simplify_aggr_init_expr.
+ (cp_gimplify_init_expr): Don't call it here.
+ (gimplify_aggr_init_expr): Remove.
+
+2003-08-19 Jason Merrill <jason@redhat.com>
+
+ * typeck.c (build_array_ref): Also build ARRAY_REFs from
+ INDIRECT_REFs of ARRAY_TYPE.
+
+ * semantics.c (finish_id_expression): Unshare aliases.
+
+2003-08-12 Diego Novillo <dnovillo@redhat.com>
+
+ * optimize.c (optimize_function): Do not call dump_function.
+
+2003-08-08 Jason Merrill <jason@redhat.com>
+
+ * optimize.c (optimize_function): Restore support for
+ !keep_function_tree_in_gimple_form.
+
+2003-07-27 Andreas Jaeger <aj@suse.de>
+
+ * cp-lang.c: Convert K&R prototypes to ISO C90.
+ * cp-simplify.c: Likewise.
+ * cp-mudflap.c: Likewise.
+
+2003-06-13 Frank Ch. Eigler <fche@redhat.com>
+
+ * semantics.c (expand_body): Call mudflap_c_function just before
+ rtl expansion of function body; don't interfere with inlining.
+ * optimize.c (optimize_function): Remove mudflap call.
+
+2003-06-13 Diego Novillo <dnovillo@redhat.com>
+
+ * cp-lang.c, cp-simplify.c, cp-tree.h, decl.c, optimize.c,
+ semantics.c, tree.c: Rename SIMPLE to GIMPLE everywhere.
+
+2003-06-05 Frank Ch. Eigler <fche@redhat.com>
+
+ * cp-mudflap.c (mflang_register_call): Give the synthetic decl
+ undefined (not zero) size.
+
+2003-06-05 Frank Ch. Eigler <fche@redhat.com>
+
+ * cp-mudflap.c (mx_flag): Remove. Update callers to use mf_mark.
+
+2003-05-24 Diego Novillo <dnovillo@redhat.com>
+
+ * Make-lang.in (optimize.o): Add dependency on tree-simple.h
+ * decl.c (grokdeclarator): Don't abort when the declarator is
+ ERROR_MARK_NODE.
+ * optimize.c (optimize_function): Unshare all trees after
+ optimizing inline calls.
+
+2003-05-12 Diego Novillo <dnovillo@redhat.com>
+
+ * class.c (dump_array): Call CONSTRUCTOR_ELTS to access
+ the operand of a CONSTRUCTOR node.
+
+2003-05-07 Diego Novillo <dnovillo@redhat.com>
+
+ * decl.c (grokdeclarator): Fix thinko in handling
+ ERROR_MARK declarators.
+
+2003-05-07 Diego Novillo <dnovillo@redhat.com>
+
+ * decl.c (grokdeclarator): Handle ERROR_MARK declarators.
+
+2003-05-07 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (expand_body): Call expand_stmt when
+ -fdisable-simple is given.
+
+2003-04-21 Jeff Law <law@redhat.com>
+
+ * optimize.c (optimize_function_tree): Do run the tree-ssa
+ optimizers.
+
+2003-04-16 Jeff Law <law@redhat.com>
+
+ * optimize.c (optimize_function): No longer check
+ flag_disable_simple.
+
+2003-04-15 Jeff Law <law@redhat.com>
+
+ * pt.c (instantiate_decl): If CFUN is null, then we will
+ need to push to the toplevel.
+
+ * Makefile.in (decl.o): Depends on tree-flow.h.
+ * decl.c (finish_function): Call set_has_hidden_use when
+ nullifying returns for named value return optimization.
+
+2003-04-02 Jason Merrill <jason@redhat.com>
+
+ * cp-simplify.c (cp_simplify_expr) <case EMPTY_CLASS_EXPR>:
+ Change type of constant to RECORD_TYPE.
+
+2003-03-10 Jeff Law <law@redhat.com>
+
+ * optimize.c (optimize_function): Avoid unnecessary
+ simplification of the function tree.
+
+2003-03-02 Diego Novillo <dnovillo@redhat.com>
+
+ * decl.c: Replace DECL_SOURCE_LOCATION with TREE_LOCUS
+ everywhere.
+
+2003-02-28 Frank Ch. Eigler <fche@redhat.com>
+
+ * decl2.c (finish_file): Adjust timing of mudflap_finish_file call
+ to account for unit-at-a-time compilation.
+
+2003-02-07 Jason Merrill <jason@redhat.com>
+
+ * cp-simplify.c (cp_simplify_expr): Handle BASELINK.
+
+ * parser.c (cp_parser_primary_expression): Unshare a COMPONENT_REF
+ from an ALIAS_DECL.
+
+2003-02-05 Jason Merrill <jason@redhat.com>
+
+ * cp-simplify.c (genericize_try_block): Do genericize catch blocks.
+
+2003-02-03 Diego Novillo <dnovillo@redhat.com>
+
+ * parser.c (cp_parser_asm_definition): Call finish_asm_stmt with
+ 'volatile_p' directly.
+ * typeck.c (build_binary_op): Initialize variable 'type'.
+ * Make-lang.in (cp/tree.o-warn): Add -Wno-error.
+
+2003-01-29 Frank Ch. Eigler <fche@redhat.com>
+
+ * cp-mudflap.c (mflang_register_call): Adapt to mf-runtime.h API
+ change.
+
+2003-01-15 Jeff Law <law@redhat.com>
+
+ * class.c: Use TREE_FILENAME and TREE_LINENO to extract
+ file/line information from tree nodes. Remove EXPR_WITH_FILE_LOCATION
+ nodes. Use annotate_with_file_line to attach file/line information
+ to tree nodes. Use TREE_LOCUS to copy file/line information
+ from one node to another.
+ * decl2.c, error.c, init.c, lex.c, method.c: Likewise.
+ * optimize.c: Likewise.
+ * cp-tree.def (TINST_LEVEL): New tree node.
+ * cp-tree.h (TINST_DECL): Update now that we no longer use
+ EXPR_WITH_FILE_LOCATION to represent the TINST_DECL information.
+ (TINST_FILE, TINST_LINE): Kill.
+ * decl.c: Use TREE_FILENAME and TREE_LINENO to extract
+ file/line information from tree nodes. Use annotate_witH_file_line
+ to add file/line information to tree nodes. Use TREE_LOCUS
+ to copy file/line information from one node to another.
+ (duplicate_decls): Make sure to copy TREE_LOCUS information
+ from the old decl to the new decl.
+ (finish_function): Save and restore file/line information
+ around genericizing the function tree.
+ * pt.c (lookup_template_class): Use TREE_LOCUS to copy file/line
+ information from one node to another.
+ (push_tinst_level): Generate a TINST_LEVEL node rather than
+ using EXPR_WITH_FILE_LOCATION nodes. Use annotate_with_file_line
+ to annotate the new node with file/line information.
+ (pop_tinst_level): Use TREE_LINENO and TREE_FILENAME to extract
+ file/line information from nodes.
+ (tsubst_friend_function, instantiate_class_template): Likewise.
+ (tsubst_decl, instantiate_decl, tsubst_enum): Likewise.
+ * semantics.c: Use annotate_with_file_line to annotate tree
+ nodes with file/line information. Use TREE_FILENAME and TREE_LINENO
+ to extract file/line information from tree nodes.
+ (expand_body): Restore file/line information slightly earlier.
+ tree.c (cp_walk_subtrees): Set lineno appropriately.
+ (cp_copy_res_decl_for_inlining): Use TREE_LOCUS to copy file/line
+ information from one node to another.
+
+2003-01-13 Frank Ch. Eigler <fche@redhat.com>
+
+ Prototype C++ mudflap support.
+ * Make-lang.in (CXX_OBJS): Add cp/cp-mudflap.o and dependencies.
+ * cp-mudflap.c: New file with C++ front-end mflang_* routines.
+ * decl2.c (finish_file): Divert to mudflap if appropriate.
+ * optimize.c (optimize_function): Ditto.
+
+2003-01-02 Jason Merrill <jason@redhat.com>
+
+ * Make-lang.in (CXX_C_OBJS): Replace old-tree-inline.o with
+ tree-inline.o.
+
+ * optimize.c (dump_function): Move to ../tree-dump.c.
+
+ * cp-simplify.c (cp_simplify_expr): Handle PTRMEM_CST, INIT_EXPR,
+ MODIFY_EXPR and EMPTY_CLASS_EXPR.
+ (cp_simplify_stmt): Handle USING_STMT.
+ (cp_simplify_init_expr): New fn.
+ * cvt.c (build_up_reference): Don't push the decl.
+ * class.c (build_vtable_entry_ref, build_vtbl_ref_1): Unshare the
+ vtable address.
+ * init.c (build_vtbl_address): Likewise.
+ * cp-lang.c (LANG_HOOKS_UNSAVE_EXPR_NOW): Remove.
+ * decl.c (lookup_name_real): Unshare the expansion of an ALIAS_DECL.
+ (finish_function): Don't genericize templates.
+ * parse.y (parse_asm_stmt): Fix prototype.
+ * semantics.c (expand_body): Don't expand if we saw errors.
+ Drop support for expanding non-GENERIC code.
+
+ * cp-simplify.c (cp_simplify_stmt): Handle HANDLER and EH_SPEC_BLOCK.
+ (genericize_try_block): Always build a TRY_CATCH_EXPR.
+ (genericize_catch_block): New fn.
+ (genericize_eh_spec_block): New fn.
+ (cp_simplify_expr): Handle THROW_EXPR and MUST_NOT_THROW_EXPR.
+ (simplify_must_not_throw_expr): New fn.
+ * except.c (wrap_cleanups_r): Make the MUST_NOT_THROW_EXPR void.
+ (build_throw): Likewise.
+
+2002-12-14 Jason Merrill <jason@redhat.com>
+
+ * optimize.c (dump_function): Use pretty dumpers.
+ (optimize_function): Don't do .original dump here.
+
+2002-12-03 Diego Novillo <dnovillo@redhat.com>
+
+ * cp-simplify.c: Include coretypes.h and tm.h.
+
+2002-11-24 Jason Merrill <jason@redhat.com>
+
+ Gimplify C++ cleanups.
+ * decl.c (finish_function): Call c_genericize.
+ * cp-simplify.c (cp_simplify_stmt): New fn.
+ (genericize_try_block): New fn.
+ (cp_simplify_expr): Move INIT_EXPR/TARGET_EXPR code
+ to ../gimplify.c. Handle AGGR_INIT_EXPR.
+ (simplify_target_expr): Move to ../gimplify.c.
+ (maybe_fixup_loop_cond): Remove.
+ (simplify_aggr_init_expr): Split out from...
+ * semantics.c (simplify_aggr_init_exprs_r): ...here.
+ (expand_body): Don't simplify AGGR_INIT_EXPRs here
+ if we're gimplifying. Handle expanding generic trees.
+ * tree.c (init_tree): Set lang_simplify_stmt.
+ * cp-tree.h: Declare the new fns.
+
+ * optimize.c (optimize_function): Do pretty dumps.
+
+2002-10-04 Jason Merrill <jason@redhat.com>
+
+ * Make-lang.in (CXX_C_OBJS): Add gimplify.o.
+
+2002-09-24 Jason Merrill <jason@redhat.com>
+
+ * parse.y (parse_asm_stmt): New fn.
+ (simple_stmt): Use it.
+ * semantics.c (finish_asm_stmt): Change cv_qualifier parm to
+ volatile_p.
+ * cp-tree.h: Adjust prototype.
+ * pt.c (tsubst_expr): Adjust call.
+
+2002-08-23 Diego Novillo <dnovillo@redhat.com>
+
+ * Make-lang.in (CXX_C_OBJS): Add tree-dchain.o
+
+2002-08-11 Jason Merrill <jason@redhat.com>
+
+ * cp-simplify.c (maybe_fixup_loop_cond): Move here.
+ (cp_simplify_expr): Call it.
+ (simplify_target_expr): Remove pre_p parm.
+
+2002-08-09 Jason Merrill <jason@redhat.com>
+
+ * cp-simplify.c (cp_simplify_expr): New fn.
+ (simplify_target_expr): New fn.
+ (cp_simplify_function_tree): Remove.
+ * cp-lang.c (LANG_HOOKS_SIMPLIFY_FUNCTION_TREE): Don't define.
+ (LANG_HOOKS_SIMPLIFY_EXPR): Define.
+ * optimize.c (optimize_function): De-hook simplify_function_tree.
+ * cp-tree.h: Declare cp_simplify_expr.
+
+2002-07-17 Daniel Berlin <dberlin@dberlin.org>
+
+ * Make-lang.in (CXX_C_OBJS): Add tree-alias-ecr.c,
+ tree-alias-type.o, tree-alias-steen.o, disjoint-set.o.
+
+2002-06-21 Andreas Jaeger <aj@suse.de>
+
+ * Make-lang.in (cp-simplify.o): New.
+
+2002-06-18 Jason Merrill <jason@redhat.com>
+
+ * cp-simplify.c: New file.
+ * Make-lang.in: Add it.
+ * cp-tree.h: Declare cp_simplify_function_tree.
+ * cp-lang.c (LANG_HOOKS_SIMPLIFY_FUNCTION_TREE): Define.
+ * optimize.c (optimize_function): Call tree optimizers (but not yet).
+
+Local Variables:
+mode: change-log
+change-log-default-name: "ChangeLog.tree-ssa"
+End:
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 0f934f225a3..bf4b0fe850f 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -73,14 +73,16 @@ g++-cross$(exeext): g++$(exeext)
# Shared with C front end:
CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o \
- c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o
+ c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \
+ c-simplify.o tree-inline.o
# Language-specific object files.
CXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
cp/class.o cp/decl2.o cp/error.o cp/lex.o cp/parser.o cp/ptree.o cp/rtti.o \
cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
- cp/mangle.o cp/cp-lang.o cp/name-lookup.o cp/cxx-pretty-print.o
+ cp/mangle.o cp/cp-lang.o cp/name-lookup.o cp/cxx-pretty-print.o \
+ cp/cp-simplify.o tree-mudflap.o cp/cp-mudflap.o
# Use strict warnings for this front end.
cp-warn = $(STRICT_WARN) $(WERROR)
@@ -221,7 +223,7 @@ cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h langhooks.h \
cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h stack.h \
output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(RTL_H) \
cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h \
- debug.h gt-cp-decl.h gtype-cp.h timevar.h
+ debug.h gt-cp-decl.h gtype-cp.h timevar.h $(TREE_FLOW_H)
cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
output.h except.h toplev.h $(RTL_H) c-common.h gt-cp-decl2.h cgraph.h
cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_P_H) \
@@ -257,12 +259,16 @@ cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) cp/lex.h except.h toplev.h
tree-inline.h cgraph.h
cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h
cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h integrate.h insn-config.h \
- input.h $(PARAMS_H) debug.h tree-inline.h
+ input.h $(PARAMS_H) debug.h tree-inline.h tree-simple.h
cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) toplev.h real.h gt-cp-mangle.h \
$(TARGET_H) $(TM_P_H)
cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) diagnostic.h gt-cp-parser.h \
output.h
+cp/cp-simplify.o: cp/cp-simplify.c $(CXX_TREE_H) toplev.h c-common.h \
+ $(TM_H) coretypes.h
+cp/cp-mudflap.o: cp/cp-mudflap.c $(CXX_TREE_H) toplev.h c-common.h \
+ $(TM_H) coretypes.h
cp/name-lookup.o: cp/name-lookup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(CXX_TREE_H) timevar.h gt-cp-name-lookup.h toplev.h \
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4f38c7ed622..c4892e949e4 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -346,7 +346,7 @@ build_call (tree function, tree parms)
TREE_VALUE (tmp), t);
}
- function = build (CALL_EXPR, result_type, function, parms);
+ function = build (CALL_EXPR, result_type, function, parms, NULL_TREE);
TREE_HAS_CONSTRUCTOR (function) = is_constructor;
TREE_NOTHROW (function) = nothrow;
@@ -4331,7 +4331,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
static tree
call_builtin_trap (tree type)
{
- tree fn = IDENTIFIER_GLOBAL_VALUE (get_identifier ("__builtin_trap"));
+ tree fn = implicit_built_in_decls[BUILT_IN_TRAP];
my_friendly_assert (fn != NULL, 20030927);
fn = build_call (fn, NULL_TREE);
@@ -4560,7 +4560,7 @@ build_over_call (struct z_candidate *cand, int flags)
tree expr;
tree return_type;
return_type = TREE_TYPE (TREE_TYPE (fn));
- expr = build (CALL_EXPR, return_type, fn, args);
+ expr = build (CALL_EXPR, return_type, fn, args, NULL_TREE);
if (!VOID_TYPE_P (return_type))
require_complete_type (return_type);
return convert_from_reference (expr);
@@ -4768,16 +4768,11 @@ build_over_call (struct z_candidate *cand, int flags)
else if (TREE_CODE (arg) == TARGET_EXPR
|| TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
{
- tree address;
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (args), 0));
val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
- address = build_unary_op (ADDR_EXPR, val, 0);
- /* Avoid a warning about this expression, if the address is
- never used. */
- TREE_USED (address) = 1;
- return address;
+ return val;
}
}
else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
@@ -4813,7 +4808,7 @@ build_over_call (struct z_candidate *cand, int flags)
val = build (MODIFY_EXPR, as_base, to_as_base, arg_as_base);
val = convert_to_void (val, NULL);
val = build (COMPOUND_EXPR, type, val, save_to);
- TREE_NO_UNUSED_WARNING (val) = 1;
+ TREE_NO_WARNING (val) = 1;
}
return val;
@@ -4936,7 +4931,8 @@ build_java_interface_fn_ref (tree fn, tree instance)
iface);
return error_mark_node;
}
- iface_ref = build1 (ADDR_EXPR, build_pointer_type (iface), iface_ref);
+ iface_ref = build_address (iface_ref);
+ iface_ref = convert (build_pointer_type (iface), iface_ref);
/* Determine the itable index of FN. */
i = 1;
@@ -5360,7 +5356,7 @@ build_new_method_call (tree instance, tree fns, tree args,
call = (build_min_non_dep
(CALL_EXPR, call,
build_min_nt (COMPONENT_REF, orig_instance, orig_fns),
- orig_args));
+ orig_args, NULL_TREE));
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 13d6d03c9a5..6d2fef50205 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -335,14 +335,14 @@ build_base_path (enum tree_code code,
/* In a base member initializer, we cannot rely on
the vtable being set up. We have to use the vtt_parm. */
tree derived = BINFO_INHERITANCE_CHAIN (v_binfo);
-
- v_offset = build (PLUS_EXPR, TREE_TYPE (current_vtt_parm),
- current_vtt_parm, BINFO_VPTR_INDEX (derived));
-
- v_offset = build1 (INDIRECT_REF,
- TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived))),
- v_offset);
-
+ tree t;
+
+ t = TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived)));
+ t = build_pointer_type (t);
+ v_offset = convert (t, current_vtt_parm);
+ v_offset = build (PLUS_EXPR, t, v_offset,
+ BINFO_VPTR_INDEX (derived));
+ v_offset = build_indirect_ref (v_offset, NULL);
}
else
v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
@@ -354,6 +354,8 @@ build_base_path (enum tree_code code,
build_pointer_type (ptrdiff_type_node),
v_offset);
v_offset = build_indirect_ref (v_offset, NULL);
+ TREE_CONSTANT (v_offset) = 1;
+ TREE_INVARIANT (v_offset) = 1;
offset = convert_to_integer (ptrdiff_type_node,
size_diffop (offset,
@@ -513,7 +515,7 @@ build_vtbl_ref_1 (tree instance, tree idx)
tree binfo = lookup_base (fixed_type, basetype,
ba_ignore|ba_quiet, NULL);
if (binfo)
- vtbl = BINFO_VTABLE (binfo);
+ vtbl = unshare_expr (BINFO_VTABLE (binfo));
}
if (!vtbl)
@@ -522,6 +524,8 @@ build_vtbl_ref_1 (tree instance, tree idx)
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
+ TREE_CONSTANT (aref) |= TREE_CONSTANT (vtbl) && TREE_CONSTANT (idx);
+ TREE_INVARIANT (aref) = TREE_CONSTANT (aref);
return aref;
}
@@ -7277,10 +7281,7 @@ dfs_accumulate_vtbl_inits (tree binfo,
/* Figure out the position to which the VPTR should point. */
vtbl = TREE_PURPOSE (l);
- vtbl = build1 (ADDR_EXPR,
- vtbl_ptr_type_node,
- vtbl);
- TREE_CONSTANT (vtbl) = 1;
+ vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl);
index = size_binop (PLUS_EXPR,
size_int (non_fn_entries),
size_int (list_length (TREE_VALUE (l))));
@@ -7288,7 +7289,6 @@ dfs_accumulate_vtbl_inits (tree binfo,
TYPE_SIZE_UNIT (vtable_entry_type),
index);
vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
- TREE_CONSTANT (vtbl) = 1;
}
if (ctor_vtbl_p)
@@ -7462,8 +7462,6 @@ build_vtbl_initializer (tree binfo,
/* Take the address of the function, considering it to be of an
appropriate generic type. */
init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
- /* The address of a function can't change. */
- TREE_CONSTANT (init) = 1;
}
/* And add it to the chain of initializers. */
@@ -7480,6 +7478,7 @@ build_vtbl_initializer (tree binfo,
TREE_OPERAND (init, 0),
build_int_2 (i, 0));
TREE_CONSTANT (fdesc) = 1;
+ TREE_INVARIANT (fdesc) = 1;
vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits);
}
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 3c2a311e9ca..3d737ad502a 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -35,11 +35,12 @@ Boston, MA 02111-1307, USA. */
enum c_language_kind c_language = clk_cxx;
static HOST_WIDE_INT cxx_get_alias_set (tree);
-static bool ok_to_generate_alias_set_for_type (tree);
static bool cxx_warn_unused_global_decl (tree);
static tree cp_expr_size (tree);
static size_t cp_tree_size (enum tree_code);
static bool cp_var_mod_type_p (tree);
+static int cxx_types_compatible_p (tree, tree);
+static int cp_expand_decl (tree);
static void cxx_initialize_diagnostics (diagnostic_context *);
#undef LANG_HOOKS_NAME
@@ -70,14 +71,14 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#define LANG_HOOKS_EXPAND_CONSTANT cplus_expand_constant
#undef LANG_HOOKS_EXPAND_EXPR
#define LANG_HOOKS_EXPAND_EXPR cxx_expand_expr
+#undef LANG_HOOKS_EXPAND_DECL
+#define LANG_HOOKS_EXPAND_DECL cp_expand_decl
#undef LANG_HOOKS_SAFE_FROM_P
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
#undef LANG_HOOKS_PARSE_FILE
#define LANG_HOOKS_PARSE_FILE c_common_parse_file
#undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
#define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL cxx_dup_lang_specific_decl
-#undef LANG_HOOKS_UNSAVE_EXPR_NOW
-#define LANG_HOOKS_UNSAVE_EXPR_NOW cxx_unsave_expr_now
#undef LANG_HOOKS_MAYBE_BUILD_CLEANUP
#define LANG_HOOKS_MAYBE_BUILD_CLEANUP cxx_maybe_build_cleanup
#undef LANG_HOOKS_TRUTHVALUE_CONVERSION
@@ -110,8 +111,6 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL cxx_warn_unused_global_decl
#undef LANG_HOOKS_WRITE_GLOBALS
#define LANG_HOOKS_WRITE_GLOBALS lhd_do_nothing
-#undef LANG_HOOKS_DECL_UNINIT
-#define LANG_HOOKS_DECL_UNINIT c_decl_uninit
#undef LANG_HOOKS_UPDATE_DECL_AFTER_SAVING
#define LANG_HOOKS_UPDATE_DECL_AFTER_SAVING cp_update_decl_after_saving
@@ -120,11 +119,8 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#define LANG_HOOKS_FUNCTION_INIT cxx_push_function_context
#undef LANG_HOOKS_FUNCTION_FINAL
#define LANG_HOOKS_FUNCTION_FINAL cxx_pop_function_context
-
-#undef LANG_HOOKS_RTL_EXPAND_START
-#define LANG_HOOKS_RTL_EXPAND_START cxx_expand_function_start
-#undef LANG_HOOKS_RTL_EXPAND_STMT
-#define LANG_HOOKS_RTL_EXPAND_STMT expand_stmt
+#undef LANG_HOOKS_FUNCTION_MISSING_NORETURN_OK_P
+#define LANG_HOOKS_FUNCTION_MISSING_NORETURN_OK_P cp_missing_noreturn_ok_p
/* Attribute hooks. */
#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
@@ -145,7 +141,7 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
cp_add_pending_fn_decls
#undef LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P
#define LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P \
- cp_is_overload_p
+ cp_tree_chain_matters_p
#undef LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P
#define LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P \
cp_auto_var_in_fn_p
@@ -156,8 +152,6 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P anon_aggr_type_p
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P cp_var_mod_type_p
-#undef LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS
-#define LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS c_estimate_num_insns
#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN cp_dump_tree
#undef LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN
@@ -186,8 +180,12 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR cxx_incomplete_type_error
#undef LANG_HOOKS_TYPE_PROMOTES_TO
#define LANG_HOOKS_TYPE_PROMOTES_TO cxx_type_promotes_to
+#undef LANG_HOOKS_TYPES_COMPATIBLE_P
+#define LANG_HOOKS_TYPES_COMPATIBLE_P cxx_types_compatible_p
#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
+#undef LANG_HOOKS_GIMPLIFY_EXPR
+#define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
/* Each front end provides its own hooks, for toplev.c. */
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
@@ -233,60 +231,6 @@ const char *const tree_code_name[] = {
};
#undef DEFTREECODE
-/* Check if a C++ type is safe for aliasing.
- Return TRUE if T safe for aliasing FALSE otherwise. */
-
-static bool
-ok_to_generate_alias_set_for_type (tree t)
-{
- if (TYPE_PTRMEMFUNC_P (t))
- return true;
- if (AGGREGATE_TYPE_P (t))
- {
- if ((TREE_CODE (t) == RECORD_TYPE) || (TREE_CODE (t) == UNION_TYPE))
- {
- tree fields;
- /* Backend-created structs are safe. */
- if (! CLASS_TYPE_P (t))
- return true;
- /* PODs are safe. */
- if (! CLASSTYPE_NON_POD_P(t))
- return true;
- /* Classes with virtual baseclasses are not. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (t))
- return false;
- /* Recursively check the base classes. */
- if (TYPE_BINFO (t) != NULL && TYPE_BINFO_BASETYPES (t) != NULL)
- {
- int i;
- for (i = 0; i < TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t)); i++)
- {
- tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), i);
- if (!ok_to_generate_alias_set_for_type (BINFO_TYPE (binfo)))
- return false;
- }
- }
- /* Check all the fields. */
- for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
- {
- if (TREE_CODE (fields) != FIELD_DECL)
- continue;
- if (! ok_to_generate_alias_set_for_type (TREE_TYPE (fields)))
- return false;
- }
- return true;
- }
- else if (TREE_CODE (t) == ARRAY_TYPE)
- return ok_to_generate_alias_set_for_type (TREE_TYPE (t));
- else
- /* This should never happen, we dealt with all the aggregate
- types that can appear in C++ above. */
- abort ();
- }
- else
- return true;
-}
-
/* Special routine to get the alias set for C++. */
static HOST_WIDE_INT
@@ -297,13 +241,8 @@ cxx_get_alias_set (tree t)
complete type. */
return get_alias_set (TYPE_CONTEXT (t));
- if (/* It's not yet safe to use alias sets for some classes in C++. */
- !ok_to_generate_alias_set_for_type (t)
- /* Nor is it safe to use alias sets for pointers-to-member
- functions, due to the fact that there may be more than one
- RECORD_TYPE type corresponding to the same pointer-to-member
- type. */
- || TYPE_PTRMEMFUNC_P (t))
+ /* Punt on PMFs until we canonicalize functions properly. */
+ if (TYPE_PTRMEMFUNC_P (t))
return 0;
return c_common_get_alias_set (t);
@@ -354,6 +293,35 @@ cp_expr_size (tree exp)
return lhd_expr_size (exp);
}
+/* Expand DECL if it declares an entity not handled by the
+ common code. */
+
+static int
+cp_expand_decl (tree decl)
+{
+ if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
+ {
+ /* Let the back-end know about this variable. */
+ if (!anon_aggr_type_p (TREE_TYPE (decl)))
+ emit_local_var (decl);
+ else
+ expand_anon_union_decl (decl, NULL_TREE,
+ DECL_ANON_UNION_ELEMS (decl));
+ }
+ else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+ make_rtl_for_local_static (decl);
+ else
+ return 0;
+
+ return 1;
+}
+
+int
+cp_tree_chain_matters_p (tree t)
+{
+ return cp_is_overload_p (t) || c_tree_chain_matters_p (t);
+}
+
/* Langhook for tree_size: determine size of our 'x' and 'c' nodes. */
static size_t
cp_tree_size (enum tree_code code)
@@ -388,6 +356,11 @@ cp_var_mod_type_p (tree type)
return false;
}
+static int cxx_types_compatible_p (tree x, tree y)
+{
+ return same_type_ignoring_top_level_qualifiers_p (x, y);
+}
+
/* Construct a C++-aware pretty-printer for CONTEXT. It is assumed
that CONTEXT->printer is an already constructed basic pretty_printer. */
static void
diff --git a/gcc/cp/cp-mudflap.c b/gcc/cp/cp-mudflap.c
new file mode 100644
index 00000000000..878dc8a1c85
--- /dev/null
+++ b/gcc/cp/cp-mudflap.c
@@ -0,0 +1,108 @@
+/* Mudflap: narrow-pointer bounds-checking by tree rewriting:
+ C++ front-end interface.
+
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Contributed by Frank Ch. Eigler <fche@redhat.com>
+ and Graydon Hoare <graydon@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+
+#include "config.h"
+#include "errors.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "tree-inline.h"
+#include "cp-tree.h"
+#include "c-common.h"
+#include "diagnostic.h"
+#include "output.h"
+#include "varray.h"
+#include "tree-mudflap.h"
+#include "target.h"
+#include "flags.h"
+#include "rtl.h"
+#include "toplev.h"
+
+
+/* Initialize the global tree nodes that correspond to mf-runtime.h
+ declarations. */
+tree
+mflang_lookup_decl (const char* name)
+{
+ tree decl = lookup_name (get_identifier (name), 1);
+ if (decl == NULL_TREE)
+ internal_error ("mudflap: cannot find declaration of `%s' from mf-runtime.h",
+ name);
+
+ return decl;
+}
+
+
+/* Emit a synthetic CTOR function for the current file. Populate it from
+ the enqueued __mf_register calls. Register it with the constructors. */
+
+void
+mflang_flush_calls (tree enqueued_call_stmt_chain)
+{
+ tree fnname, fndecl, body;
+
+ /* Short-circuit! */
+ if (enqueued_call_stmt_chain == NULL_TREE)
+ return;
+
+ /* Create a ctor function declaration. */
+ fnname = get_identifier ("__static_initialization_and_destruction_mudflap");
+
+ start_function (void_list_node,
+ make_call_declarator (fnname, void_list_node, NULL_TREE,
+ NULL_TREE),
+ NULL_TREE, SF_DEFAULT);
+
+ TREE_PUBLIC (current_function_decl) = 0;
+ TREE_USED (current_function_decl) = 1;
+ DECL_ARTIFICIAL (current_function_decl) = 1;
+ mf_mark (current_function_decl);
+
+ /* Generate the body, one statement at a time. */
+ body = begin_compound_stmt (/*has_no_scope=*/false);
+
+ while (enqueued_call_stmt_chain)
+ {
+ tree next = TREE_CHAIN (enqueued_call_stmt_chain);
+ finish_expr_stmt (enqueued_call_stmt_chain);
+ enqueued_call_stmt_chain = next;
+ }
+
+ finish_compound_stmt (body);
+ fndecl = finish_function (0);
+
+ /* NB: We cannot call expand_or_defer_fn here, since that goes through
+ the callgraph queue. This queue will have already been processed by the
+ time this function is running. */
+ expand_body (fndecl);
+ if (targetm.have_ctors_dtors)
+ (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
+ DEFAULT_INIT_PRIORITY);
+ else
+ /* By this time, it's too late to do this:
+ static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors); */
+ abort ();
+}
diff --git a/gcc/cp/cp-simplify.c b/gcc/cp/cp-simplify.c
new file mode 100644
index 00000000000..af302ee5476
--- /dev/null
+++ b/gcc/cp/cp-simplify.c
@@ -0,0 +1,236 @@
+/* C++-specific tree lowering bits; see also c-simplify.c and tree-simple.c.
+
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Jason Merrill <jason@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "cp-tree.h"
+#include "c-common.h"
+#include "toplev.h"
+#include "tree-simple.h"
+
+static void genericize_try_block (tree *);
+static void genericize_catch_block (tree *);
+static void genericize_eh_spec_block (tree *);
+static void gimplify_must_not_throw_expr (tree *, tree *);
+static void cp_gimplify_init_expr (tree *, tree *, tree *);
+
+/* Genericize a C++ _STMT. Called from c_gimplify_stmt. */
+
+int
+cp_gimplify_stmt (tree *stmt_p, tree *next_p ATTRIBUTE_UNUSED)
+{
+ tree stmt = *stmt_p;
+ switch (TREE_CODE (stmt))
+ {
+ case TRY_BLOCK:
+ genericize_try_block (stmt_p);
+ return 1;
+
+ case HANDLER:
+ genericize_catch_block (stmt_p);
+ return 1;
+
+ case EH_SPEC_BLOCK:
+ genericize_eh_spec_block (stmt_p);
+ return 1;
+
+ case USING_STMT:
+ /* Just ignore for now. Eventually we will want to pass this on to
+ the debugger. */
+ *stmt_p = build_empty_stmt ();
+ return 1;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+/* Genericize a TRY_BLOCK. */
+
+static void
+genericize_try_block (tree *stmt_p)
+{
+ tree body = TRY_STMTS (*stmt_p);
+ tree cleanup = TRY_HANDLERS (*stmt_p);
+
+ c_gimplify_stmt (&body);
+
+ if (CLEANUP_P (*stmt_p))
+ /* A cleanup is an expression, so it doesn't need to be genericized. */;
+ else
+ c_gimplify_stmt (&cleanup);
+
+ *stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
+}
+
+/* Genericize a HANDLER by converting to a CATCH_EXPR. */
+
+static void
+genericize_catch_block (tree *stmt_p)
+{
+ tree type = HANDLER_TYPE (*stmt_p);
+ tree body = HANDLER_BODY (*stmt_p);
+
+ c_gimplify_stmt (&body);
+
+ /* FIXME should the caught type go in TREE_TYPE? */
+ *stmt_p = build (CATCH_EXPR, void_type_node, type, body);
+}
+
+/* Genericize an EH_SPEC_BLOCK by converting it to a
+ TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
+
+static void
+genericize_eh_spec_block (tree *stmt_p)
+{
+ tree body = EH_SPEC_STMTS (*stmt_p);
+ tree allowed = EH_SPEC_RAISES (*stmt_p);
+ tree failure = build_call (call_unexpected_node,
+ tree_cons (NULL_TREE, build_exc_ptr (),
+ NULL_TREE));
+ c_gimplify_stmt (&body);
+
+ *stmt_p = gimple_build_eh_filter (body, allowed, failure);
+}
+
+/* Do C++-specific gimplification. Args are as for gimplify_expr. */
+
+int
+cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
+{
+ switch (TREE_CODE (*expr_p))
+ {
+ case PTRMEM_CST:
+ *expr_p = cplus_expand_constant (*expr_p);
+ return GS_OK;
+
+ case AGGR_INIT_EXPR:
+ simplify_aggr_init_expr (expr_p);
+ return GS_OK;
+
+ case THROW_EXPR:
+ /* FIXME communicate throw type to backend, probably by moving
+ THROW_EXPR into ../tree.def. */
+ *expr_p = TREE_OPERAND (*expr_p, 0);
+ return GS_OK;
+
+ case MUST_NOT_THROW_EXPR:
+ gimplify_must_not_throw_expr (expr_p, pre_p);
+ return GS_OK;
+
+ case INIT_EXPR:
+ case MODIFY_EXPR:
+ cp_gimplify_init_expr (expr_p, pre_p, post_p);
+ return GS_OK;
+
+ case EMPTY_CLASS_EXPR:
+ {
+ /* Yes, an INTEGER_CST with RECORD_TYPE. */
+ tree i = build_int_2 (0, 0);
+ TREE_TYPE (i) = TREE_TYPE (*expr_p);
+ *expr_p = i;
+ }
+ return GS_OK;
+
+ case BASELINK:
+ *expr_p = BASELINK_FUNCTIONS (*expr_p);
+ return GS_OK;
+
+ default:
+ return c_gimplify_expr (expr_p, pre_p, post_p);
+ }
+}
+
+/* Gimplify initialization from an AGGR_INIT_EXPR. */
+
+static void
+cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
+{
+ tree from = TREE_OPERAND (*expr_p, 1);
+ tree to = TREE_OPERAND (*expr_p, 0);
+ tree sub;
+
+ /* If we are initializing something from a TARGET_EXPR, strip the
+ TARGET_EXPR and initialize it directly. */
+ /* 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) == TARGET_EXPR)
+ from = TARGET_EXPR_INITIAL (from);
+
+ sub = from;
+
+ /* If we are initializing from a STMT_EXPR, extract the returned
+ expression. */
+ if (TREE_CODE (from) == STMT_EXPR)
+ sub = EXPR_STMT_EXPR (stmt_expr_last_stmt (from));
+
+ /* Look through any COMPOUND_EXPRs. */
+ while (TREE_CODE (sub) == COMPOUND_EXPR)
+ sub = TREE_OPERAND (sub, 1);
+
+ /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
+ replace the slot operand with our target.
+
+ Should we add a target parm to gimplify_expr instead? No, as in this
+ case we want to replace the INIT_EXPR. */
+ if (TREE_CODE (sub) == AGGR_INIT_EXPR)
+ {
+ gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
+ TREE_OPERAND (sub, 2) = to;
+ *expr_p = from;
+
+ /* The initialization is now a side-effect, so the container can
+ become void. This is important for a STMT_EXPR, so we don't try
+ to voidify it later by creating a temporary. */
+ if (from != sub)
+ TREE_TYPE (from) = void_type_node;
+ }
+}
+
+/* Gimplify a MUST_NOT_THROW_EXPR. */
+
+static void
+gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
+{
+ tree stmt = *expr_p;
+ tree temp = voidify_wrapper_expr (stmt);
+ tree body = TREE_OPERAND (stmt, 0);
+
+ gimplify_stmt (&body);
+
+ stmt = gimple_build_eh_filter (body, NULL_TREE,
+ build_call (terminate_node, NULL_TREE));
+
+ if (temp)
+ {
+ append_to_statement_list (stmt, pre_p);
+ *expr_p = temp;
+ }
+ else
+ *expr_p = stmt;
+}
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index d64752068a3..63a18af378e 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -257,6 +257,15 @@ DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", 'e', 1)
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
+/* Template instantiation level node.
+
+ Operand 1 contains the original DECL node and can be accessed via TINST_DECL.
+
+ A stack of template instantiation nodes is kept through the TREE_CHAIN
+ fields of these nodes. */
+
+DEFTREECODE (TINST_LEVEL, "TINST_LEVEL", 'e', 1)
+
/*
Local variables:
mode:c
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 37170e2ca71..7efe55d8061 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3137,12 +3137,9 @@ typedef enum unification_kind_t {
DEDUCE_ORDER
} unification_kind_t;
-/* Macros for operating on a template instantiation level node, represented
- by an EXPR_WITH_FILE_LOCATION. */
+/* Macros for operating on a template instantiation level node. */
-#define TINST_DECL(NODE) EXPR_WFL_NODE (NODE)
-#define TINST_LINE(NODE) EXPR_WFL_LINENO (NODE)
-#define TINST_FILE(NODE) EXPR_WFL_FILENAME (NODE)
+#define TINST_DECL(NODE) TREE_OPERAND (NODE, 0)
/* in class.c */
@@ -3709,6 +3706,7 @@ extern tmpl_spec_kind current_tmpl_spec_kind (int);
extern tree cp_fname_init (const char *, tree *);
extern tree check_elaborated_type_specifier (enum tag_types, tree, bool);
extern void warn_extern_redeclared_static (tree, tree);
+extern bool cp_missing_noreturn_ok_p (tree);
extern bool have_extern_spec;
@@ -4047,7 +4045,7 @@ extern void finish_handler (tree);
extern void finish_cleanup (tree, tree);
extern tree begin_compound_stmt (bool);
extern tree finish_compound_stmt (tree);
-extern tree finish_asm_stmt (tree, tree, tree, tree, tree);
+extern tree finish_asm_stmt (int, tree, tree, tree, tree);
extern tree finish_label_stmt (tree);
extern void finish_label_decl (tree);
extern void finish_subobject (tree);
@@ -4087,7 +4085,6 @@ extern void finish_decl_cleanup (tree, tree);
extern void finish_eh_cleanup (tree);
extern void expand_body (tree);
extern void cxx_expand_function_start (void);
-extern tree nullify_returns_r (tree *, int *, void *);
extern void do_pushlevel (scope_kind);
extern tree do_poplevel (void);
extern void finish_mem_initializers (tree);
@@ -4098,11 +4095,14 @@ extern void expand_or_defer_fn (tree);
extern void check_accessibility_of_qualified_id (tree, tree, tree);
extern tree finish_qualified_id_expr (tree, tree, bool, bool);
extern void simplify_aggr_init_expr (tree *);
+extern void finalize_nrv (tree *, tree, tree);
/* in tree.c */
extern void lang_check_failed (const char *, int,
const char *);
extern tree stabilize_expr (tree, tree *);
+extern void stabilize_call (tree, tree *);
+extern bool stabilize_init (tree, tree *);
extern tree cxx_unsave_expr_now (tree);
extern tree cxx_maybe_build_cleanup (tree);
extern void init_tree (void);
@@ -4166,6 +4166,7 @@ extern tree find_tree (tree, tree);
extern linkage_kind decl_linkage (tree);
extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
void*, void*);
+extern int cp_tree_chain_matters_p (tree);
extern int cp_cannot_inline_tree_fn (tree*);
extern tree cp_add_pending_fn_decls (void*,tree);
extern int cp_is_overload_p (tree);
@@ -4283,6 +4284,10 @@ extern tree mangle_ref_init_variable (tree);
/* in dump.c */
extern bool cp_dump_tree (void *, tree);
+/* in cp-simplify.c */
+extern int cp_gimplify_expr (tree *, tree *, tree *);
+extern int cp_gimplify_stmt (tree *, tree *);
+
/* -- end of C++ */
/* In order for the format checking to accept the C++ frontend
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index bf906fd969e..b22948106b2 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -810,7 +810,7 @@ convert_to_void (tree expr, const char *implicit)
/* The second part of a compound expr contains the value. */
tree op1 = TREE_OPERAND (expr,1);
tree new_op1 = convert_to_void
- (op1, (implicit && !TREE_NO_UNUSED_WARNING (expr)
+ (op1, (implicit && !TREE_NO_WARNING (expr)
? "right-hand operand of comma" : NULL));
if (new_op1 != op1)
@@ -887,7 +887,8 @@ convert_to_void (tree expr, const char *implicit)
if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr)))
{
- if (implicit && !TREE_SIDE_EFFECTS (expr) && warn_unused_value)
+ if (implicit && warn_unused_value
+ && !TREE_SIDE_EFFECTS (expr) && !TREE_NO_WARNING (expr))
warning ("%s has no effect", implicit);
expr = build1 (CONVERT_EXPR, void_type_node, expr);
}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 17b625f668c..21f82548eaa 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -51,6 +51,7 @@ Boston, MA 02111-1307, USA. */
#include "diagnostic.h"
#include "debug.h"
#include "timevar.h"
+#include "tree-flow.h"
static tree grokparms (tree, tree *);
static const char *redeclaration_error_message (tree, tree);
@@ -114,7 +115,6 @@ static tree check_special_function_return_type
static tree push_cp_library_fn (enum tree_code, tree);
static tree build_cp_library_fn (tree, enum tree_code, tree);
static void store_parm_decls (tree);
-static int cp_missing_noreturn_ok_p (tree);
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
@@ -499,28 +499,6 @@ poplevel (int keep, int reverse, int functionbody)
else
decls = current_binding_level->names;
- /* Output any nested inline functions within this block
- if they weren't already output. */
- for (decl = decls; decl; decl = TREE_CHAIN (decl))
- if (TREE_CODE (decl) == FUNCTION_DECL
- && ! TREE_ASM_WRITTEN (decl)
- && DECL_INITIAL (decl) != NULL_TREE
- && TREE_ADDRESSABLE (decl)
- && decl_function_context (decl) == current_function_decl)
- {
- /* If this decl was copied from a file-scope decl
- on account of a block-scope extern decl,
- propagate TREE_ADDRESSABLE to the file-scope decl. */
- if (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE)
- TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
- else
- {
- push_function_context ();
- output_inline_function (decl);
- pop_function_context ();
- }
- }
-
/* When not in function-at-a-time mode, expand_end_bindings will
warn about unused variables. But, in function-at-a-time mode
expand_end_bindings is not passed the list of variables in the
@@ -2406,9 +2384,11 @@ push_switch (tree switch_stmt)
void
pop_switch (void)
{
- struct cp_switch *cs;
+ struct cp_switch *cs = switch_stack;
+
+ /* Emit warnings as needed. */
+ c_do_switch_warnings (cs->cases, cs->switch_stmt);
- cs = switch_stack;
splay_tree_delete (cs->cases);
switch_stack = switch_stack->next;
free (cs);
@@ -2878,9 +2858,6 @@ cxx_init_decl_processing (void)
/* Create all the identifiers we need. */
initialize_predefined_identifiers ();
- /* Fill in back-end hooks. */
- lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
-
/* Create the global variables. */
push_to_top_level ();
@@ -3060,7 +3037,8 @@ cxx_init_decl_processing (void)
start_fname_decls ();
/* Show we use EH for cleanups. */
- using_eh_for_cleanups ();
+ if (flag_exceptions)
+ using_eh_for_cleanups ();
}
/* Generate an initializer for a function naming variable from
@@ -4544,7 +4522,7 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
asm-specification, indicates that the variable should be
placed in a particular register. */
if (DECL_REGISTER (decl))
- DECL_C_HARD_REGISTER (decl) = 1;
+ DECL_HARD_REGISTER (decl) = 1;
}
/* We don't create any RTL for local variables. */
@@ -7283,6 +7261,13 @@ grokdeclarator (tree declarator,
type = create_array_type_for_decl (dname, type, size);
+ if (declarator
+ && (TREE_CODE (declarator) == INDIRECT_REF
+ || TREE_CODE (declarator) == ADDR_EXPR))
+ /* We can never complete an array type which is the target of a
+ pointer, so go ahead and lay it out. */
+ layout_type (type);
+
ctype = NULL_TREE;
}
break;
@@ -7768,6 +7753,7 @@ grokdeclarator (tree declarator,
}
if (declarator == NULL_TREE
+ || TREE_CODE (declarator) == ERROR_MARK
|| TREE_CODE (declarator) == IDENTIFIER_NODE
|| (TREE_CODE (declarator) == TEMPLATE_ID_EXPR
&& (TREE_CODE (type) == FUNCTION_TYPE
@@ -9935,7 +9921,9 @@ build_enumerator (tree name, tree value, tree enumtype)
decl = build_decl (CONST_DECL, name, type);
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
- TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
+ TREE_CONSTANT (decl) = 1;
+ TREE_INVARIANT (decl) = 1;
+ TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = value;
if (context && context == current_class_type)
@@ -10730,10 +10718,8 @@ finish_function (int flags)
of curly braces for a function. */
my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
- /* Set up the named return value optimization, if we can. Here, we
- eliminate the copy from the nrv into the RESULT_DECL and any cleanup
- for the nrv. genrtl_start_function and declare_return_variable
- handle making the nrv and RESULT_DECL share space. */
+ /* Set up the named return value optimization, if we can. Candidate
+ variables are selected in check_return_value. */
if (current_function_return_value)
{
tree r = current_function_return_value;
@@ -10750,16 +10736,9 @@ finish_function (int flags)
/* Skip the artificial function body block. */
&& (outer = BLOCK_SUBBLOCKS (BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl))),
chain_member (r, BLOCK_VARS (outer))))
- {
-
- DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl));
- walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
- nullify_returns_r, r);
- }
- else
- /* Clear it so genrtl_start_function and declare_return_variable
- know we're not optimizing. */
- current_function_return_value = NULL_TREE;
+ finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl));
+
+ current_function_return_value = NULL_TREE;
}
/* Remember that we were in class scope. */
@@ -10802,9 +10781,21 @@ finish_function (int flags)
&& (DECL_INLINE (fndecl) || processing_template_decl))
warning ("no return statement in function returning non-void");
- /* We're leaving the context of this function, so zap cfun.
- It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
- tree_rest_of_compilation. */
+ /* Store the end of the function, so that we get good line number
+ info for the epilogue. */
+ cfun->function_end_locus = input_location;
+
+ /* Genericize before inlining. */
+ if (!processing_template_decl)
+ {
+ c_genericize (fndecl);
+
+ /* Handle attribute((warn_unused_result)). Relies on gimple input. */
+ c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
+ }
+
+ /* We're leaving the context of this function, so zap cfun. It's still in
+ DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation. */
cfun = NULL;
current_function_decl = NULL;
@@ -11178,7 +11169,7 @@ build_void_list_node (void)
return t;
}
-static int
+bool
cp_missing_noreturn_ok_p (tree decl)
{
/* A missing noreturn is ok for the `main' function. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 5730d369efc..4c36eb5549c 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -46,8 +46,10 @@ Boston, MA 02111-1307, USA. */
#include "cpplib.h"
#include "target.h"
#include "c-common.h"
+#include "tree-mudflap.h"
#include "cgraph.h"
#include "tree-inline.h"
+
extern cpp_reader *parse_in;
/* This structure contains information about the initializations
@@ -2587,7 +2589,7 @@ finish_file (void)
timevar_push (TV_VARCONST);
emit_support_tinfos ();
-
+
do
{
tree t;
@@ -2872,6 +2874,11 @@ finish_file (void)
cgraph_optimize ();
}
+ /* Emit mudflap static registration function. This must be done
+ after all the user functions have been expanded. */
+ if (flag_mudflap)
+ mudflap_finish_file ();
+
/* Now, issue warnings about static, but not defined, functions,
etc., and emit debugging information. */
walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
@@ -2885,12 +2892,12 @@ finish_file (void)
to a file. */
{
int flags;
- FILE *stream = dump_begin (TDI_all, &flags);
+ FILE *stream = dump_begin (TDI_tu, &flags);
if (stream)
{
dump_node (global_namespace, flags & ~TDF_SLIM, stream);
- dump_end (TDI_all, stream);
+ dump_end (TDI_tu, stream);
}
}
@@ -2932,7 +2939,7 @@ build_offset_ref_call_from_tree (tree fn, tree args)
20030708);
if (type_dependent_expression_p (fn)
|| any_type_dependent_arguments_p (args))
- return build_min_nt (CALL_EXPR, fn, args);
+ return build_min_nt (CALL_EXPR, fn, args, NULL_TREE);
/* Transform the arguments and add the implicit "this"
parameter. That must be done before the FN is transformed
@@ -2962,7 +2969,7 @@ build_offset_ref_call_from_tree (tree fn, tree args)
expr = build_function_call (fn, args);
if (processing_template_decl && expr != error_mark_node)
- return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args);
+ return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args, NULL_TREE);
return expr;
}
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index e313c16f39d..6e186503bad 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -47,7 +47,7 @@ static cxx_pretty_printer scratch_pretty_printer;
# define NEXT_CODE(T) (TREE_CODE (TREE_TYPE (T)))
#define reinit_global_formatting_buffer() \
- output_clear_message_text (scratch_buffer)
+ pp_clear_output_area (scratch_buffer)
static const char *args_to_string (tree, int);
static const char *assop_to_string (enum tree_code);
@@ -1604,10 +1604,6 @@ dump_expr (tree t, int flags)
break;
}
- case EXPR_WITH_FILE_LOCATION:
- dump_expr (EXPR_WFL_NODE (t), flags);
- break;
-
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
{
@@ -2191,8 +2187,7 @@ print_instantiation_full_context (diagnostic_context *context)
decl_as_string (TINST_DECL (p),
TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
- location.line = TINST_LINE (p);
- location.file = TINST_FILE (p);
+ location = *EXPR_LOCUS (p);
p = TREE_CHAIN (p);
}
}
@@ -2211,8 +2206,7 @@ print_instantiation_partial_context (diagnostic_context *context,
loc.file, loc.line,
decl_as_string (TINST_DECL (t),
TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
- loc.line = TINST_LINE (t);
- loc.file = TINST_FILE (t);
+ loc = *EXPR_LOCUS (t);
}
pp_verbatim (context->printer, "%s:%d: instantiated from here\n",
loc.file, loc.line);
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 7e172d62e6b..79f1dfac0d9 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -47,7 +47,6 @@ static tree do_end_catch (tree);
static bool decl_is_java_type (tree decl, int err);
static void initialize_handler_parm (tree, tree);
static tree do_allocate_exception (tree);
-static tree stabilize_throw_expr (tree, tree *);
static tree wrap_cleanups_r (tree *, int *, void *);
static int complete_ptr_ref_or_void_ptr_p (tree, tree);
static bool is_admissible_throw_operand (tree);
@@ -145,7 +144,7 @@ build_eh_type_type (tree type)
mark_used (exp);
- return build1 (ADDR_EXPR, ptr_type_node, exp);
+ return convert (ptr_type_node, build_address (exp));
}
tree
@@ -507,7 +506,6 @@ do_allocate_exception (tree type)
NULL_TREE));
}
-#if 0
/* Call __cxa_free_exception from a cleanup. This is never invoked
directly, but see the comment for stabilize_throw_expr. */
@@ -526,7 +524,6 @@ do_free_exception (tree ptr)
return build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE));
}
-#endif
/* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
Called from build_throw via walk_tree_without_duplicates. */
@@ -558,58 +555,6 @@ wrap_cleanups_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
return NULL_TREE;
}
-/* Like stabilize_expr, but specifically for a thrown expression. When
- throwing a temporary class object, we want to construct it directly into
- the thrown exception, so we look past the TARGET_EXPR and stabilize the
- arguments of the call instead.
-
- The case where EXP is a call to a function returning a class is a bit of
- a grey area in the standard; it's unclear whether or not it should be
- allowed to throw. I'm going to say no, as that allows us to optimize
- this case without worrying about deallocating the exception object if it
- does. The alternatives would be either not optimizing this case, or
- wrapping the initialization in a TRY_CATCH_EXPR to call do_free_exception
- rather than in a MUST_NOT_THROW_EXPR, for this case only. */
-
-static tree
-stabilize_throw_expr (tree exp, tree *initp)
-{
- tree init_expr;
-
- if (TREE_CODE (exp) == TARGET_EXPR
- && TREE_CODE (TARGET_EXPR_INITIAL (exp)) == AGGR_INIT_EXPR
- && flag_elide_constructors)
- {
- tree aggr_init = AGGR_INIT_EXPR_CHECK (TARGET_EXPR_INITIAL (exp));
- tree args = TREE_OPERAND (aggr_init, 1);
- tree newargs = NULL_TREE;
- tree *p = &newargs;
-
- init_expr = void_zero_node;
- for (; args; args = TREE_CHAIN (args))
- {
- tree arg = TREE_VALUE (args);
- tree arg_init_expr;
-
- arg = stabilize_expr (arg, &arg_init_expr);
-
- if (TREE_SIDE_EFFECTS (arg_init_expr))
- init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
- arg_init_expr);
- *p = tree_cons (NULL_TREE, arg, NULL_TREE);
- p = &TREE_CHAIN (*p);
- }
- TREE_OPERAND (aggr_init, 1) = newargs;
- }
- else
- {
- exp = stabilize_expr (exp, &init_expr);
- }
-
- *initp = init_expr;
- return exp;
-}
-
/* Build a throw expression. */
tree
@@ -663,6 +608,7 @@ build_throw (tree exp)
tree object, ptr;
tree tmp;
tree temp_expr, allocate_expr;
+ bool elided;
fn = get_identifier ("__cxa_throw");
if (!get_global_value_if_present (fn, &fn))
@@ -703,11 +649,6 @@ build_throw (tree exp)
the call to __cxa_allocate_exception first (which doesn't
matter, since it can't throw). */
- /* Pre-evaluate the thrown expression first, since if we allocated
- the space first we would have to deal with cleaning it up if
- evaluating this expression throws. */
- exp = stabilize_throw_expr (exp, &temp_expr);
-
/* Allocate the space for the exception. */
allocate_expr = do_allocate_exception (TREE_TYPE (exp));
allocate_expr = get_target_expr (allocate_expr);
@@ -715,6 +656,8 @@ build_throw (tree exp)
object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
object = build_indirect_ref (object, NULL);
+ elided = (TREE_CODE (exp) == TARGET_EXPR);
+
/* And initialize the exception object. */
exp = build_init (object, exp, LOOKUP_ONLYCONVERTING);
if (exp == error_mark_node)
@@ -723,10 +666,35 @@ build_throw (tree exp)
return error_mark_node;
}
- exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp);
+ /* Pre-evaluate the thrown expression first, since if we allocated
+ the space first we would have to deal with cleaning it up if
+ evaluating this expression throws.
+
+ The case where EXP the initializer is a call to a constructor or a
+ function returning a class is a bit of a grey area in the
+ standard; it's unclear whether or not it should be allowed to
+ throw. We used to say no, as that allowed us to optimize this
+ case without worrying about deallocating the exception object if
+ it does. But that conflicted with expectations (PR 13944) and the
+ EDG compiler; now we wrap the initialization in a TRY_CATCH_EXPR
+ to call do_free_exception rather than in a MUST_NOT_THROW_EXPR,
+ for this case only.
+
+ Note that we don't check the return value from stabilize_init
+ because it will only return false in cases where elided is true,
+ and therefore we don't need to work around the failure to
+ preevaluate. */
+ stabilize_init (exp, &temp_expr);
+
+ if (elided)
+ exp = build (TRY_CATCH_EXPR, void_type_node, exp,
+ do_free_exception (ptr));
+ else
+ exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp);
+
/* Prepend the allocation. */
exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
- if (temp_expr != void_zero_node)
+ if (temp_expr)
{
/* Prepend the calculation of the throw expression. Also, force
any cleanups from the expression to be evaluated here so that
@@ -921,11 +889,10 @@ check_handlers_1 (tree master, tree handlers)
if (TREE_TYPE (handler)
&& can_convert_eh (type, TREE_TYPE (handler)))
{
- input_line = STMT_LINENO (handler);
- warning ("exception of type `%T' will be caught",
- TREE_TYPE (handler));
- input_line = STMT_LINENO (master);
- warning (" by earlier handler for `%T'", type);
+ warning ("%Hexception of type `%T' will be caught",
+ EXPR_LOCUS (handler), TREE_TYPE (handler));
+ warning ("%H by earlier handler for `%T'",
+ EXPR_LOCUS (master), type);
break;
}
}
@@ -943,11 +910,8 @@ check_handlers (tree handlers)
if (TREE_CHAIN (handler) == NULL_TREE)
/* No more handlers; nothing to shadow. */;
else if (TREE_TYPE (handler) == NULL_TREE)
- {
- input_line = STMT_LINENO (handler);
- pedwarn
- ("`...' handler must be the last handler for its try block");
- }
+ pedwarn ("%H`...' handler must be the last handler for"
+ " its try block", EXPR_LOCUS (handler));
else
check_handlers_1 (handler, TREE_CHAIN (handler));
}
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index 00f8676e180..e12c6a4a64f 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -73,6 +73,9 @@ cplus_expand_constant (tree cst)
}
/* Hook used by expand_expr to expand language-specific tree codes. */
+/* ??? The only thing that should be here are things needed to expand
+ constant initializers; everything else should be handled by the
+ gimplification routines. Are EMPTY_CLASS_EXPR or BASELINK needed? */
rtx
cxx_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier,
@@ -81,7 +84,6 @@ cxx_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier,
tree type = TREE_TYPE (exp);
enum machine_mode mode = TYPE_MODE (type);
enum tree_code code = TREE_CODE (exp);
- rtx ret;
/* No sense saving up arithmetic to be done
if it's all in the wrong mode to form part of an address.
@@ -99,17 +101,6 @@ cxx_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier,
case OFFSET_REF:
/* Offset refs should not make it through to here. */
abort ();
- return const0_rtx;
-
- case THROW_EXPR:
- expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
- return const0_rtx;
-
- case MUST_NOT_THROW_EXPR:
- expand_eh_region_start ();
- ret = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
- expand_eh_region_end_must_not_throw (build_call (terminate_node, 0));
- return ret;
case EMPTY_CLASS_EXPR:
/* We don't need to generate any code for an empty class. */
@@ -122,7 +113,4 @@ cxx_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier,
default:
return c_expand_expr (exp, target, tmode, modifier, alt_rtl);
}
- abort ();
- /* NOTREACHED */
- return NULL;
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 6811aaab58e..8cf0019cfab 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -248,7 +248,10 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
/* In all cases, the initializer is a constant. */
if (init)
- TREE_CONSTANT (init) = 1;
+ {
+ TREE_CONSTANT (init) = 1;
+ TREE_INVARIANT (init) = 1;
+ }
return init;
}
@@ -728,12 +731,9 @@ build_vtbl_address (tree binfo)
TREE_USED (vtbl) = 1;
/* Now compute the address to use when initializing the vptr. */
- vtbl = BINFO_VTABLE (binfo_for);
+ vtbl = unshare_expr (BINFO_VTABLE (binfo_for));
if (TREE_CODE (vtbl) == VAR_DECL)
- {
- vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
- TREE_CONSTANT (vtbl) = 1;
- }
+ vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
return vtbl;
}
@@ -767,7 +767,8 @@ expand_virtual_init (tree binfo, tree decl)
TREE_TYPE (vtt_parm),
vtt_parm,
vtt_index);
- vtbl2 = build1 (INDIRECT_REF, TREE_TYPE (vtbl), vtbl2);
+ vtbl2 = build_indirect_ref (vtbl2, NULL);
+ vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
/* The actual initializer is the VTT value only in the subobject
constructor. In maybe_clone_body we'll substitute NULL for
@@ -1143,9 +1144,13 @@ build_init (tree decl, tree init, int flags)
{
tree expr;
- if (IS_AGGR_TYPE (TREE_TYPE (decl))
- || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expr = build_aggr_init (decl, init, flags);
+ else if (CLASS_TYPE_P (TREE_TYPE (decl)))
+ expr = build_special_member_call (decl, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, init),
+ TYPE_BINFO (TREE_TYPE (decl)),
+ LOOKUP_NORMAL|flags);
else
expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
@@ -1825,7 +1830,7 @@ build_new (tree placement, tree decl, tree init, int use_global_new)
/* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */
rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
- TREE_NO_UNUSED_WARNING (rval) = 1;
+ TREE_NO_WARNING (rval) = 1;
return rval;
}
@@ -1908,7 +1913,7 @@ static tree
build_new_1 (tree exp)
{
tree placement, init;
- tree true_type, size, rval, t;
+ tree true_type, size, rval;
/* The type of the new-expression. (This type is always a pointer
type.) */
tree pointer_type;
@@ -1949,6 +1954,7 @@ build_new_1 (tree exp)
address of the first array element. This node is a VAR_DECL, and
is therefore reusable. */
tree data_addr;
+ tree init_preeval_expr = NULL_TREE;
placement = TREE_OPERAND (exp, 0);
type = TREE_OPERAND (exp, 1);
@@ -2009,7 +2015,9 @@ build_new_1 (tree exp)
tree class_addr, alloc_decl;
tree class_decl = build_java_class_ref (true_type);
static const char alloc_name[] = "_Jv_AllocObject";
+
use_java_new = 1;
+ alloc_decl = NULL;
if (!get_global_value_if_present (get_identifier (alloc_name),
&alloc_decl))
{
@@ -2115,18 +2123,8 @@ build_new_1 (tree exp)
placement delete. */
if (placement_allocation_fn_p)
{
- tree inits = NULL_TREE;
- t = TREE_CHAIN (TREE_OPERAND (alloc_call, 1));
- for (; t; t = TREE_CHAIN (t))
- if (TREE_SIDE_EFFECTS (TREE_VALUE (t)))
- {
- tree init;
- TREE_VALUE (t) = stabilize_expr (TREE_VALUE (t), &init);
- if (inits)
- inits = build (COMPOUND_EXPR, void_type_node, inits, init);
- else
- inits = init;
- }
+ tree inits;
+ stabilize_call (alloc_call, &inits);
if (inits)
alloc_expr = build (COMPOUND_EXPR, TREE_TYPE (alloc_expr), inits,
alloc_expr);
@@ -2169,27 +2167,43 @@ build_new_1 (tree exp)
data_addr = alloc_node;
}
- /* Now initialize the allocated object. */
+ /* Now initialize the allocated object. Note that we preevaluate the
+ initialization expression, apart from the actual constructor call or
+ assignment--we do this because we want to delay the allocation as long
+ as possible in order to minimize the size of the exception region for
+ placement delete. */
if (is_initialized)
{
+ bool stable;
+
init_expr = build_indirect_ref (data_addr, NULL);
if (init == void_zero_node)
init = build_default_init (full_type, nelts);
- else if (init && pedantic && has_array)
+ else if (init && has_array)
pedwarn ("ISO C++ forbids initialization in array new");
if (has_array)
- init_expr
- = build_vec_init (init_expr,
- cp_build_binary_op (MINUS_EXPR, outer_nelts,
- integer_one_node),
- init, /*from_array=*/0);
+ {
+ init_expr
+ = build_vec_init (init_expr,
+ cp_build_binary_op (MINUS_EXPR, outer_nelts,
+ integer_one_node),
+ init, /*from_array=*/0);
+
+ /* An array initialization is stable because the initialization
+ of each element is a full-expression, so the temporaries don't
+ leak out. */
+ stable = true;
+ }
else if (TYPE_NEEDS_CONSTRUCTING (type))
- init_expr = build_special_member_call (init_expr,
- complete_ctor_identifier,
- init, TYPE_BINFO (true_type),
- LOOKUP_NORMAL);
+ {
+ init_expr = build_special_member_call (init_expr,
+ complete_ctor_identifier,
+ init, TYPE_BINFO (true_type),
+ LOOKUP_NORMAL);
+ stable = stabilize_init (init_expr, &init_preeval_expr);
+ }
else
{
/* We are processing something like `new int (10)', which
@@ -2197,15 +2211,13 @@ build_new_1 (tree exp)
if (TREE_CODE (init) == TREE_LIST)
init = build_x_compound_expr_from_list (init, "new initializer");
-
+
else if (TREE_CODE (init) == CONSTRUCTOR
&& TREE_TYPE (init) == NULL_TREE)
- {
- pedwarn ("ISO C++ forbids aggregate initializer to new");
- init = digest_init (type, init, 0);
- }
+ abort ();
init_expr = build_modify_expr (init_expr, INIT_EXPR, init);
+ stable = stabilize_init (init_expr, &init_preeval_expr);
}
if (init_expr == error_mark_node)
@@ -2232,31 +2244,24 @@ build_new_1 (tree exp)
(placement_allocation_fn_p
? alloc_call : NULL_TREE));
- /* Ack! First we allocate the memory. Then we set our sentry
- variable to true, and expand a cleanup that deletes the memory
- if sentry is true. Then we run the constructor, and finally
- clear the sentry.
-
- It would be nice to be able to handle this without the sentry
- variable, perhaps with a TRY_CATCH_EXPR, but this doesn't
- work. We allocate the space first, so if there are any
- temporaries with cleanups in the constructor args we need this
- EH region to extend until end of full-expression to preserve
- nesting.
-
- If the backend had some mechanism so that we could force the
- allocation to be expanded after all the other args to the
- constructor, that would fix the nesting problem and we could
- do away with this complexity. But that would complicate other
- things; in particular, it would make it difficult to bail out
- if the allocation function returns null. Er, no, it wouldn't;
- we just don't run the constructor. The standard says it's
- unspecified whether or not the args are evaluated.
-
- FIXME FIXME FIXME inline invisible refs as refs. That way we
- can preevaluate value parameters. */
-
- if (cleanup)
+ if (!cleanup)
+ /* We're done. */;
+ else if (stable)
+ /* This is much simpler if we were able to preevaluate all of
+ the arguments to the constructor call. */
+ init_expr = build (TRY_CATCH_EXPR, void_type_node,
+ init_expr, cleanup);
+ else
+ /* Ack! First we allocate the memory. Then we set our sentry
+ variable to true, and expand a cleanup that deletes the
+ memory if sentry is true. Then we run the constructor, and
+ finally clear the sentry.
+
+ We need to do this because we allocate the space first, so
+ if there are any temporaries with cleanups in the
+ constructor args and we weren't able to preevaluate them, we
+ need this EH region to extend until end of full-expression
+ to preserve nesting. */
{
tree end, sentry, begin;
@@ -2277,6 +2282,7 @@ build_new_1 (tree exp)
build (COMPOUND_EXPR, void_type_node, init_expr,
end));
}
+
}
}
else
@@ -2309,6 +2315,9 @@ build_new_1 (tree exp)
rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
}
+ if (init_preeval_expr)
+ rval = build (COMPOUND_EXPR, TREE_TYPE (rval), init_preeval_expr, rval);
+
/* Convert to the final type. */
rval = build_nop (pointer_type, rval);
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 1ade1a91f3f..044f2895c0c 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -317,7 +317,6 @@ static inline bool
get_global_value_if_present (tree id, tree *decl)
{
tree global_value = namespace_binding (id, global_namespace);
-
if (global_value)
*decl = global_value;
return global_value != NULL;
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 2fd10599151..1be4d8afdcc 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -36,6 +36,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "hashtab.h"
#include "debug.h"
#include "tree-inline.h"
+#include "flags.h"
+#include "langhooks.h"
+#include "diagnostic.h"
+#include "tree-dump.h"
+#include "tree-simple.h"
/* Prototypes. */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6fb8da5d158..fdc171e041f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -3842,7 +3842,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|| any_type_dependent_arguments_p (args)))
{
postfix_expression
- = build_min_nt (CALL_EXPR, postfix_expression, args);
+ = build_min_nt (CALL_EXPR, postfix_expression,
+ args, NULL_TREE);
break;
}
@@ -5473,14 +5474,14 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
{
tree statement;
cp_token *token;
- int statement_line_number;
+ location_t statement_locus;
/* There is no statement yet. */
statement = NULL_TREE;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
- /* Remember the line number of the first token in the statement. */
- statement_line_number = token->location.line;
+ /* Remember the location of the first token in the statement. */
+ statement_locus = token->location;
/* If this is a keyword, then that will often determine what kind of
statement we have. */
if (token->type == CPP_KEYWORD)
@@ -5556,7 +5557,10 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
/* Set the line number for the statement. */
if (statement && STATEMENT_CODE_P (TREE_CODE (statement)))
- STMT_LINENO (statement) = statement_line_number;
+ {
+ SET_EXPR_LOCUS (statement, NULL);
+ annotate_with_locus (statement, statement_locus);
+ }
}
/* Parse a labeled-statement.
@@ -9867,10 +9871,8 @@ cp_parser_asm_definition (cp_parser* parser)
/* Create the ASM_STMT. */
if (at_function_scope_p ())
{
- asm_stmt =
- finish_asm_stmt (volatile_p
- ? ridpointers[(int) RID_VOLATILE] : NULL_TREE,
- string, outputs, inputs, clobbers);
+ asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
+ inputs, clobbers);
/* If the extended syntax was not used, mark the ASM_STMT. */
if (!extended_p)
ASM_INPUT_P (asm_stmt) = 1;
@@ -11787,7 +11789,7 @@ cp_parser_class_specifier (cp_parser* parser)
{
cp_token *token;
tree type;
- tree attributes;
+ tree attributes = NULL_TREE;
int has_trailing_semicolon;
bool nested_name_specifier_p;
unsigned saved_num_template_parameter_lists;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 96ee6875a56..043e3e467c2 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -375,7 +375,9 @@ push_inline_template_parms_recursive (tree parmlist, int levels)
tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
TREE_TYPE (parm));
DECL_ARTIFICIAL (decl) = 1;
- TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
+ TREE_CONSTANT (decl) = 1;
+ TREE_INVARIANT (decl) = 1;
+ TREE_READONLY (decl) = 1;
DECL_INITIAL (decl) = DECL_INITIAL (parm);
SET_DECL_TEMPLATE_PARM_P (decl);
pushdecl (decl);
@@ -2115,6 +2117,7 @@ build_template_parm_index (int index,
TEMPLATE_PARM_DECL (t) = decl;
TREE_TYPE (t) = type;
TREE_CONSTANT (t) = TREE_CONSTANT (decl);
+ TREE_INVARIANT (t) = TREE_INVARIANT (decl);
TREE_READONLY (t) = TREE_READONLY (decl);
return t;
@@ -2137,6 +2140,7 @@ reduce_template_parm_level (tree index, tree type, int levels)
decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
+ TREE_INVARIANT (decl) = TREE_INVARIANT (orig_decl);
TREE_READONLY (decl) = TREE_READONLY (orig_decl);
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_TEMPLATE_PARM_P (decl);
@@ -2200,11 +2204,15 @@ process_template_parm (tree list, tree next)
TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
/* A template parameter is not modifiable. */
- TREE_READONLY (parm) = TREE_CONSTANT (parm) = 1;
+ TREE_CONSTANT (parm) = 1;
+ TREE_INVARIANT (parm) = 1;
+ TREE_READONLY (parm) = 1;
if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
TREE_TYPE (parm) = void_type_node;
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
- TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
+ TREE_CONSTANT (decl) = 1;
+ TREE_INVARIANT (decl) = 1;
+ TREE_READONLY (decl) = 1;
DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
processing_template_decl,
@@ -4865,7 +4873,9 @@ push_tinst_level (tree d)
return 0;
}
- new = build_expr_wfl (d, input_filename, input_line, 0);
+ new = make_node (TINST_LEVEL);
+ annotate_with_locus (new, input_location);
+ TINST_DECL (new) = d;
TREE_CHAIN (new) = current_tinst_level;
current_tinst_level = new;
@@ -4889,8 +4899,7 @@ pop_tinst_level (void)
/* Restore the filename and line number stashed away when we started
this instantiation. */
- input_line = TINST_LINE (old);
- input_filename = TINST_FILE (old);
+ input_location = *EXPR_LOCUS (old);
extract_interface_info ();
current_tinst_level = TREE_CHAIN (old);
@@ -5648,7 +5657,7 @@ instantiate_class_template (tree type)
that would be used for non-template classes. */
typedecl = TYPE_MAIN_DECL (type);
input_location = DECL_SOURCE_LOCATION (typedecl);
-
+
unreverse_member_declarations (type);
finish_struct_1 (type);
@@ -7971,15 +7980,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
break;
case LABEL_STMT:
- input_line = STMT_LINENO (t);
+ prep_stmt (t);
finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t)));
break;
- case FILE_STMT:
- input_filename = FILE_STMT_FILENAME (t);
- add_stmt (build_nt (FILE_STMT, FILE_STMT_FILENAME_NODE (t)));
- break;
-
case GOTO_STMT:
prep_stmt (t);
tmp = GOTO_DESTINATION (t);
@@ -7996,7 +8000,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case ASM_STMT:
prep_stmt (t);
tmp = finish_asm_stmt
- (ASM_CV_QUAL (t),
+ (ASM_VOLATILE_P (t),
tsubst_expr (ASM_STRING (t), args, complain, in_decl),
tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl),
tsubst_expr (ASM_INPUTS (t), args, complain, in_decl),
@@ -11151,7 +11155,7 @@ instantiate_decl (tree d, int defer_ok)
goto out;
}
- need_push = !global_bindings_p ();
+ need_push = !cfun || !global_bindings_p ();
if (need_push)
push_to_top_level ();
@@ -11164,8 +11168,7 @@ instantiate_decl (tree d, int defer_ok)
regenerate_decl_from_template (d, td);
/* We already set the file and line above. Reset them now in case
- they changed as a result of calling
- regenerate_decl_from_template. */
+ they changed as a result of calling regenerate_decl_from_template. */
input_location = DECL_SOURCE_LOCATION (d);
if (TREE_CODE (d) == VAR_DECL)
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 9e7805651ce..ac149c8c91b 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -231,7 +231,7 @@ get_tinfo_decl_dynamic (tree exp)
/* The RTTI information is at index -1. */
index = build_int_2 (-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
t = build_vtbl_ref (exp, index);
- TREE_TYPE (t) = type_info_ptr_type;
+ t = convert (type_info_ptr_type, t);
}
else
/* Otherwise return the type_info for the static type of the expr. */
@@ -797,7 +797,6 @@ tinfo_base_init (tree desc, tree target)
size_binop (MULT_EXPR,
size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE),
TYPE_SIZE_UNIT (vtable_entry_type)));
- TREE_CONSTANT (vtable_ptr) = 1;
TINFO_VTABLE_DECL (desc) = vtable_ptr;
}
@@ -807,7 +806,9 @@ tinfo_base_init (tree desc, tree target)
init = tree_cons (NULL_TREE, decay_conversion (name_decl), init);
init = build_constructor (NULL_TREE, nreverse (init));
- TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
+ TREE_CONSTANT (init) = 1;
+ TREE_INVARIANT (init) = 1;
+ TREE_STATIC (init) = 1;
init = tree_cons (NULL_TREE, init, NULL_TREE);
return init;
@@ -823,7 +824,9 @@ generic_initializer (tree desc, tree target)
tree init = tinfo_base_init (desc, target);
init = build_constructor (NULL_TREE, init);
- TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
+ TREE_CONSTANT (init) = 1;
+ TREE_INVARIANT (init) = 1;
+ TREE_STATIC (init) = 1;
return init;
}
@@ -850,7 +853,9 @@ ptr_initializer (tree desc, tree target, bool *non_public_ptr)
init);
init = build_constructor (NULL_TREE, nreverse (init));
- TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
+ TREE_CONSTANT (init) = 1;
+ TREE_INVARIANT (init) = 1;
+ TREE_STATIC (init) = 1;
return init;
}
@@ -887,7 +892,9 @@ ptm_initializer (tree desc, tree target, bool *non_public_ptr)
init);
init = build_constructor (NULL_TREE, nreverse (init));
- TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
+ TREE_CONSTANT (init) = 1;
+ TREE_INVARIANT (init) = 1;
+ TREE_STATIC (init) = 1;
return init;
}
@@ -955,7 +962,9 @@ class_initializer (tree desc, tree target, tree trail)
TREE_CHAIN (init) = trail;
init = build_constructor (NULL_TREE, init);
- TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
+ TREE_CONSTANT (init) = 1;
+ TREE_INVARIANT (init) = 1;
+ TREE_STATIC (init) = 1;
return init;
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 6e15e611317..2fea1c8b86c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -32,6 +32,7 @@
#include "tree.h"
#include "cp-tree.h"
#include "tree-inline.h"
+#include "tree-mudflap.h"
#include "except.h"
#include "lex.h"
#include "toplev.h"
@@ -41,6 +42,7 @@
#include "output.h"
#include "timevar.h"
#include "debug.h"
+#include "diagnostic.h"
#include "cgraph.h"
/* There routines provide a modular interface to perform many parsing
@@ -55,10 +57,7 @@
static tree maybe_convert_cond (tree);
static tree simplify_aggr_init_exprs_r (tree *, int *, void *);
static void emit_associated_thunks (tree);
-static void genrtl_try_block (tree);
-static void genrtl_eh_spec_block (tree);
-static void genrtl_handler (tree);
-static void cp_expand_stmt (tree);
+static tree finalize_nrv_r (tree *, int *, void *);
/* Finish processing the COND, the SUBSTMT condition for STMT. */
@@ -788,56 +787,6 @@ finish_switch_stmt (tree switch_stmt)
do_poplevel ();
}
-/* Generate the RTL for T, which is a TRY_BLOCK. */
-
-static void
-genrtl_try_block (tree t)
-{
- if (CLEANUP_P (t))
- {
- expand_eh_region_start ();
- expand_stmt (TRY_STMTS (t));
- expand_eh_region_end_cleanup (TRY_HANDLERS (t));
- }
- else
- {
- if (!FN_TRY_BLOCK_P (t))
- emit_line_note (input_location);
-
- expand_eh_region_start ();
- expand_stmt (TRY_STMTS (t));
-
- if (FN_TRY_BLOCK_P (t))
- {
- expand_start_all_catch ();
- in_function_try_handler = 1;
- expand_stmt (TRY_HANDLERS (t));
- in_function_try_handler = 0;
- expand_end_all_catch ();
- }
- else
- {
- expand_start_all_catch ();
- expand_stmt (TRY_HANDLERS (t));
- expand_end_all_catch ();
- }
- }
-}
-
-/* Generate the RTL for T, which is an EH_SPEC_BLOCK. */
-
-static void
-genrtl_eh_spec_block (tree t)
-{
- expand_eh_region_start ();
- expand_stmt (EH_SPEC_STMTS (t));
- expand_eh_region_end_allowed (EH_SPEC_RAISES (t),
- build_call (call_unexpected_node,
- tree_cons (NULL_TREE,
- build_exc_ptr (),
- NULL_TREE)));
-}
-
/* Begin a try-block. Returns a newly-created TRY_BLOCK if
appropriate. */
@@ -925,19 +874,6 @@ finish_function_handler_sequence (tree try_block)
check_handlers (TRY_HANDLERS (try_block));
}
-/* Generate the RTL for T, which is a HANDLER. */
-
-static void
-genrtl_handler (tree t)
-{
- genrtl_do_pushlevel ();
- if (!processing_template_decl)
- expand_start_catch (HANDLER_TYPE (t));
- expand_stmt (HANDLER_BODY (t));
- if (!processing_template_decl)
- expand_end_catch ();
-}
-
/* Begin a handler. Returns a HANDLER if appropriate. */
tree
@@ -1050,28 +986,17 @@ finish_compound_stmt (tree compound_stmt)
return r;
}
-/* Finish an asm-statement, whose components are a CV_QUALIFIER, a
- STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some
- CLOBBERS. */
+/* Finish an asm-statement, whose components are a STRING, some
+ OUTPUT_OPERANDS, some INPUT_OPERANDS, and some CLOBBERS. Also note
+ whether the asm-statement should be considered volatile. */
tree
-finish_asm_stmt (tree cv_qualifier,
- tree string,
- tree output_operands,
- tree input_operands,
- tree clobbers)
+finish_asm_stmt (int volatile_p, tree string, tree output_operands,
+ tree input_operands, tree clobbers)
{
tree r;
tree t;
- if (cv_qualifier != NULL_TREE
- && cv_qualifier != ridpointers[(int) RID_VOLATILE])
- {
- warning ("%s qualifier ignored on asm",
- IDENTIFIER_POINTER (cv_qualifier));
- cv_qualifier = NULL_TREE;
- }
-
if (!processing_template_decl)
{
int i;
@@ -1133,9 +1058,10 @@ finish_asm_stmt (tree cv_qualifier,
}
}
- r = build_stmt (ASM_STMT, cv_qualifier, string,
+ r = build_stmt (ASM_STMT, string,
output_operands, input_operands,
clobbers);
+ ASM_VOLATILE_P (r) = volatile_p;
return add_stmt (r);
}
@@ -1629,7 +1555,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
if (type_dependent_expression_p (fn)
|| any_type_dependent_arguments_p (args))
{
- result = build_nt (CALL_EXPR, fn, args);
+ result = build_nt (CALL_EXPR, fn, args, NULL_TREE);
KOENIG_LOOKUP_P (result) = koenig_p;
return result;
}
@@ -1704,7 +1630,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
if (processing_template_decl)
{
if (type_dependent_expression_p (object))
- return build_nt (CALL_EXPR, orig_fn, orig_args);
+ return build_nt (CALL_EXPR, orig_fn, orig_args, NULL_TREE);
object = build_non_dependent_expr (object);
}
@@ -1737,7 +1663,8 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
if (processing_template_decl)
{
- result = build (CALL_EXPR, TREE_TYPE (result), orig_fn, orig_args);
+ result = build (CALL_EXPR, TREE_TYPE (result), orig_fn,
+ orig_args, NULL_TREE);
KOENIG_LOOKUP_P (result) = koenig_p;
}
return result;
@@ -2686,7 +2613,7 @@ finish_id_expression (tree id_expression,
/* Resolve references to variables of anonymous unions
into COMPONENT_REFs. */
if (TREE_CODE (decl) == ALIAS_DECL)
- decl = DECL_INITIAL (decl);
+ decl = unshare_expr (DECL_INITIAL (decl));
}
if (TREE_DEPRECATED (decl))
@@ -2722,37 +2649,8 @@ finish_typeof (tree expr)
return type;
}
-/* Generate RTL for the statement T, and its substatements, and any
- other statements at its nesting level. */
-
-static void
-cp_expand_stmt (tree t)
-{
- switch (TREE_CODE (t))
- {
- case TRY_BLOCK:
- genrtl_try_block (t);
- break;
-
- case EH_SPEC_BLOCK:
- genrtl_eh_spec_block (t);
- break;
-
- case HANDLER:
- genrtl_handler (t);
- break;
-
- case USING_STMT:
- break;
-
- default:
- abort ();
- break;
- }
-}
-
/* Called from expand_body via walk_tree. Replace all AGGR_INIT_EXPRs
- will equivalent CALL_EXPRs. */
+ with equivalent CALL_EXPRs. */
static tree
simplify_aggr_init_exprs_r (tree* tp,
@@ -2905,7 +2803,7 @@ void
expand_body (tree fn)
{
tree saved_function;
-
+
/* Compute the appropriate object-file linkage for inline
functions. */
if (DECL_DECLARED_INLINE_P (fn))
@@ -3013,37 +2911,94 @@ expand_or_defer_fn (tree fn)
function_depth--;
}
-/* Helper function for walk_tree, used by finish_function to override all
- the RETURN_STMTs and pertinent CLEANUP_STMTs for the named return
- value optimization. */
+struct nrv_data
+{
+ tree var;
+ tree result;
+ htab_t visited;
+};
-tree
-nullify_returns_r (tree* tp, int* walk_subtrees, void* data)
+/* Helper function for walk_tree, used by finalize_nrv below. */
+
+static tree
+finalize_nrv_r (tree* tp, int* walk_subtrees, void* data)
{
- tree nrv = (tree) data;
+ struct nrv_data *dp = (struct nrv_data *)data;
+ void **slot;
/* No need to walk into types. There wouldn't be any need to walk into
non-statements, except that we have to consider STMT_EXPRs. */
if (TYPE_P (*tp))
*walk_subtrees = 0;
+ /* Change all returns to just refer to the RESULT_DECL; this is a nop,
+ but differs from using NULL_TREE in that it indicates that we care
+ about the value of the RESULT_DECL. */
else if (TREE_CODE (*tp) == RETURN_STMT)
- RETURN_STMT_EXPR (*tp) = NULL_TREE;
+ RETURN_STMT_EXPR (*tp) = dp->result;
+ /* Change all cleanups for the NRV to only run when an exception is
+ thrown. */
else if (TREE_CODE (*tp) == CLEANUP_STMT
- && CLEANUP_DECL (*tp) == nrv)
+ && CLEANUP_DECL (*tp) == dp->var)
CLEANUP_EH_ONLY (*tp) = 1;
+ /* Replace the DECL_STMT for the NRV with an initialization of the
+ RESULT_DECL, if needed. */
+ else if (TREE_CODE (*tp) == DECL_STMT
+ && DECL_STMT_DECL (*tp) == dp->var)
+ {
+ tree init;
+ if (DECL_INITIAL (dp->var)
+ && DECL_INITIAL (dp->var) != error_mark_node)
+ {
+ init = build (INIT_EXPR, void_type_node, dp->result,
+ DECL_INITIAL (dp->var));
+ DECL_INITIAL (dp->var) = error_mark_node;
+ }
+ else
+ init = NULL_TREE;
+ init = build_stmt (EXPR_STMT, init);
+ SET_EXPR_LOCUS (init, EXPR_LOCUS (*tp));
+ TREE_CHAIN (init) = TREE_CHAIN (*tp);
+ *tp = init;
+ }
+ /* And replace all uses of the NRV with the RESULT_DECL. */
+ else if (*tp == dp->var)
+ *tp = dp->result;
+
+ /* Avoid walking into the same tree more than once. Unfortunately, we
+ can't just use walk_tree_without duplicates because it would only call
+ us for the first occurrence of dp->var in the function body. */
+ slot = htab_find_slot (dp->visited, *tp, INSERT);
+ if (*slot)
+ *walk_subtrees = 0;
+ else
+ *slot = *tp;
/* Keep iterating. */
return NULL_TREE;
}
-/* Start generating the RTL for FN. */
+/* Called from finish_function to implement the named return value
+ optimization by overriding all the RETURN_STMTs and pertinent
+ CLEANUP_STMTs and replacing all occurrences of VAR with RESULT, the
+ RESULT_DECL for the function. */
void
-cxx_expand_function_start (void)
+finalize_nrv (tree *tp, tree var, tree result)
{
- /* Give our named return value the same RTL as our RESULT_DECL. */
- if (current_function_return_value)
- COPY_DECL_RTL (DECL_RESULT (cfun->decl), current_function_return_value);
+ struct nrv_data data;
+
+ /* Copy debugging information from VAR to RESULT. */
+ DECL_NAME (result) = DECL_NAME (var);
+ DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (var);
+ DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (var);
+ /* Don't forget that we take its address. */
+ TREE_ADDRESSABLE (result) = TREE_ADDRESSABLE (var);
+
+ data.var = var;
+ data.result = result;
+ data.visited = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
+ walk_tree (tp, finalize_nrv_r, &data, 0);
+ htab_delete (data.visited);
}
/* Perform initialization related to this module. */
@@ -3051,7 +3006,6 @@ cxx_expand_function_start (void)
void
init_cp_semantics (void)
{
- lang_expand_stmt = cp_expand_stmt;
}
#include "gt-cp-semantics.h"
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8dd85eae80d..1e470eb862d 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1933,9 +1933,6 @@ tree
make_ptrmem_cst (tree type, tree member)
{
tree ptrmem_cst = make_node (PTRMEM_CST);
- /* If would seem a great convenience if make_node would set
- TREE_CONSTANT for things of class `c', but it does not. */
- TREE_CONSTANT (ptrmem_cst) = 1;
TREE_TYPE (ptrmem_cst) = type;
PTRMEM_CST_MEMBER (ptrmem_cst) = member;
return ptrmem_cst;
@@ -1969,19 +1966,26 @@ cp_walk_subtrees (tree* tp,
void* htab)
{
enum tree_code code = TREE_CODE (*tp);
+ location_t save_locus;
tree result;
#define WALK_SUBTREE(NODE) \
do \
{ \
result = walk_tree (&(NODE), func, data, htab); \
- if (result) \
- return result; \
+ if (result) goto out; \
} \
while (0)
+ /* Set input_location here so we get the right instantiation context
+ if we call instantiate_decl from inlinable_function_p. */
+ save_locus = input_location;
+ if (EXPR_LOCUS (*tp))
+ input_location = *EXPR_LOCUS (*tp);
+
/* Not one of the easy cases. We must explicitly go through the
children. */
+ result = NULL_TREE;
switch (code)
{
case DEFAULT_ARG:
@@ -2019,11 +2023,14 @@ cp_walk_subtrees (tree* tp,
break;
default:
- break;
+ input_location = save_locus;
+ return c_walk_subtrees (tp, walk_subtrees_p, func, data, htab);
}
/* We didn't find what we were looking for. */
- return NULL_TREE;
+ out:
+ input_location = save_locus;
+ return result;
#undef WALK_SUBTREE
}
@@ -2132,11 +2139,10 @@ tree
cp_copy_res_decl_for_inlining (tree result,
tree fn,
tree caller,
- void* decl_map_,
+ void* decl_map_ ATTRIBUTE_UNUSED,
int* need_decl,
tree return_slot_addr)
{
- splay_tree decl_map = (splay_tree)decl_map_;
tree var;
/* If FN returns an aggregate then the caller will always pass the
@@ -2147,7 +2153,7 @@ cp_copy_res_decl_for_inlining (tree result,
references to the RESULT into references to the target. */
/* We should have an explicit return slot iff the return type is
- TREE_ADDRESSABLE. See simplify_aggr_init_expr. */
+ TREE_ADDRESSABLE. See gimplify_aggr_init_expr. */
if (TREE_ADDRESSABLE (TREE_TYPE (result))
!= (return_slot_addr != NULL_TREE))
abort ();
@@ -2164,34 +2170,6 @@ cp_copy_res_decl_for_inlining (tree result,
else
var = copy_decl_for_inlining (result, fn, caller);
- if (DECL_SAVED_FUNCTION_DATA (fn))
- {
- tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
- if (nrv)
- {
- /* We have a named return value; copy the name and source
- position so we can get reasonable debugging information, and
- register the return variable as its equivalent. */
- if (TREE_CODE (var) == VAR_DECL
- /* But not if we're initializing a variable from the
- enclosing function which already has its own name. */
- && DECL_NAME (var) == NULL_TREE)
- {
- DECL_NAME (var) = DECL_NAME (nrv);
- DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
- DECL_ABSTRACT_ORIGIN (var) = DECL_ORIGIN (nrv);
- /* Don't lose initialization info. */
- DECL_INITIAL (var) = DECL_INITIAL (nrv);
- /* Don't forget that it needs to go in the stack. */
- TREE_ADDRESSABLE (var) = TREE_ADDRESSABLE (nrv);
- }
-
- splay_tree_insert (decl_map,
- (splay_tree_key) nrv,
- (splay_tree_value) var);
- }
- }
-
return var;
}
@@ -2214,6 +2192,7 @@ cp_update_decl_after_saving (tree fn,
void
init_tree (void)
{
+ lang_gimplify_stmt = cp_gimplify_stmt;
list_hash_table = htab_create_ggc (31, list_hash, list_hash_eq, NULL);
}
@@ -2431,7 +2410,7 @@ stabilize_expr (tree exp, tree* initp)
if (!TREE_SIDE_EFFECTS (exp))
{
- init_expr = void_zero_node;
+ init_expr = NULL_TREE;
}
else if (!real_lvalue_p (exp)
|| !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp)))
@@ -2450,6 +2429,80 @@ stabilize_expr (tree exp, tree* initp)
*initp = init_expr;
return exp;
}
+
+/* Like stabilize_expr, but for a call whose args we want to
+ pre-evaluate. */
+
+void
+stabilize_call (tree call, tree *initp)
+{
+ tree inits = NULL_TREE;
+ tree t;
+
+ if (call == error_mark_node)
+ return;
+
+ if (TREE_CODE (call) != CALL_EXPR
+ && TREE_CODE (call) != AGGR_INIT_EXPR)
+ abort ();
+
+ for (t = TREE_OPERAND (call, 1); t; t = TREE_CHAIN (t))
+ if (TREE_SIDE_EFFECTS (TREE_VALUE (t)))
+ {
+ tree init;
+ TREE_VALUE (t) = stabilize_expr (TREE_VALUE (t), &init);
+ if (!init)
+ /* Nothing. */;
+ else if (inits)
+ inits = build (COMPOUND_EXPR, void_type_node, inits, init);
+ else
+ inits = init;
+ }
+
+ *initp = inits;
+}
+
+/* Like stabilize_expr, but for an initialization. If we are initializing
+ an object of class type, we don't want to introduce an extra temporary,
+ so we look past the TARGET_EXPR and stabilize the arguments of the call
+ instead. */
+
+bool
+stabilize_init (tree init, tree *initp)
+{
+ tree t = init;
+
+ if (t == error_mark_node)
+ return true;
+
+ if (TREE_CODE (t) == INIT_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR)
+ TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
+ else
+ {
+ if (TREE_CODE (t) == INIT_EXPR)
+ t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == TARGET_EXPR)
+ t = TARGET_EXPR_INITIAL (t);
+ if (TREE_CODE (t) == CONSTRUCTOR
+ && CONSTRUCTOR_ELTS (t) == NULL_TREE)
+ {
+ /* Default-initialization. */
+ *initp = NULL_TREE;
+ return true;
+ }
+
+ /* If the initializer is a COND_EXPR, we can't preevaluate
+ anything. */
+ if (TREE_CODE (t) == COND_EXPR)
+ return false;
+
+ stabilize_call (t, initp);
+ }
+
+ return true;
+}
+
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
/* Complain that some language-specific thing hanging off a tree
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index dedf4956b7e..2bfd743e090 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1379,7 +1379,6 @@ decay_conversion (tree exp)
if (!cxx_mark_addressable (exp))
return error_mark_node;
adr = build_nop (ptrtype, build_address (exp));
- TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
return adr;
}
/* This way is better for a COMPONENT_REF since it can
@@ -2160,8 +2159,7 @@ build_array_ref (tree array, tree idx)
break;
}
- if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
- && TREE_CODE (array) != INDIRECT_REF)
+ if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
{
tree rval, type;
@@ -2363,6 +2361,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
e2 = fold (build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
e2 = build_indirect_ref (e2, NULL);
TREE_CONSTANT (e2) = 1;
+ TREE_INVARIANT (e2) = 1;
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */
@@ -3436,15 +3435,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
build_type = result_type;
{
- tree result = build (resultcode, build_type, op0, op1);
- tree folded;
-
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
+ tree result = fold (build (resultcode, build_type, op0, op1));
if (final_type != 0)
- return cp_convert (final_type, folded);
- return folded;
+ result = cp_convert (final_type, result);
+ return result;
}
}
@@ -3472,7 +3466,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
static tree
pointer_diff (tree op0, tree op1, tree ptrtype)
{
- tree result, folded;
+ tree result;
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (ptrtype);
@@ -3507,11 +3501,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype)
/* Do the division. */
result = build (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1));
-
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
- return folded;
+ return fold (result);
}
/* Construct and perhaps optimize a tree representation
@@ -3634,8 +3624,6 @@ build_address (tree t)
return error_mark_node;
addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
- if (staticp (t))
- TREE_CONSTANT (addr) = 1;
return addr;
}
@@ -3645,16 +3633,9 @@ build_address (tree t)
tree
build_nop (tree type, tree expr)
{
- tree nop;
-
if (type == error_mark_node || error_operand_p (expr))
return expr;
-
- nop = build1 (NOP_EXPR, type, expr);
- if (TREE_CONSTANT (expr))
- TREE_CONSTANT (nop) = 1;
-
- return nop;
+ return build1 (NOP_EXPR, type, expr);
}
/* C++: Must handle pointers to members.
@@ -3690,9 +3671,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
else
{
if (!noconvert)
- arg = default_conversion (arg);
+ arg = default_conversion (arg);
arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
- TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
}
break;
@@ -3874,7 +3854,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
compound = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
/* Eliminate warning about unused result of + or -. */
- TREE_NO_UNUSED_WARNING (compound) = 1;
+ TREE_NO_WARNING (compound) = 1;
return compound;
}
@@ -3916,10 +3896,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
if (TREE_CODE (argtype) == REFERENCE_TYPE)
{
- arg = build1
- (CONVERT_EXPR,
- build_pointer_type (TREE_TYPE (argtype)), arg);
- TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
+ tree type = build_pointer_type (TREE_TYPE (argtype));
+ arg = build1 (CONVERT_EXPR, type, arg);
return arg;
}
else if (pedantic && DECL_MAIN_P (arg))
@@ -3937,10 +3915,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
{
- arg = build1
- (CONVERT_EXPR,
- build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
- TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
+ tree type = build_pointer_type (TREE_TYPE (TREE_TYPE (arg)));
+ arg = build1 (CONVERT_EXPR, type, arg);
}
else if (lvalue_p (arg))
/* Don't let this be an lvalue. */
@@ -4170,7 +4146,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
{
tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
arg = build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
- TREE_NO_UNUSED_WARNING (arg) = 1;
+ TREE_NO_WARNING (arg) = 1;
return arg;
}
@@ -5035,7 +5011,9 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
return cond;
/* Make sure the code to compute the rhs comes out
before the split. */
- return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
+ if (preeval)
+ cond = build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
+ return cond;
}
default:
@@ -5236,7 +5214,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
if (olhs)
{
result = build (COMPOUND_EXPR, olhstype, result, olhs);
- TREE_NO_UNUSED_WARNING (result) = 1;
+ TREE_NO_WARNING (result) = 1;
return result;
}
return convert_for_assignment (olhstype, result, "assignment",
@@ -5348,7 +5326,8 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn)
u = tree_cons (pfn_field, pfn,
build_tree_list (delta_field, delta));
u = build_constructor (type, u);
- TREE_CONSTANT (u) = TREE_CONSTANT (pfn) && TREE_CONSTANT (delta);
+ TREE_CONSTANT (u) = TREE_CONSTANT (pfn) & TREE_CONSTANT (delta);
+ TREE_INVARIANT (u) = TREE_INVARIANT (pfn) & TREE_INVARIANT (delta);
TREE_STATIC (u) = (TREE_CONSTANT (u)
&& (initializer_constant_valid_p (pfn, TREE_TYPE (pfn))
!= NULL_TREE)
@@ -5998,9 +5977,7 @@ check_return_expr (tree retval)
returned expression uses the chosen variable somehow. And people expect
this restriction, anyway. (jason 2000-11-19)
- See finish_function, cxx_expand_function_start, and
- cp_copy_res_decl_for_inlining for other pieces of this
- optimization. */
+ See finish_function and finalize_nrv for the rest of this optimization. */
if (fn_returns_value_p && flag_elide_constructors)
{
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index b49d4201c50..2c6b843a7f0 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -997,8 +997,13 @@ process_init_constructor (tree type, tree init, tree* elts)
complete_array_type (type, result, /*do_default=*/0);
if (init)
TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init);
- if (allconstant) TREE_CONSTANT (result) = 1;
- if (allconstant && allsimple) TREE_STATIC (result) = 1;
+ if (allconstant)
+ {
+ TREE_CONSTANT (result) = 1;
+ TREE_INVARIANT (result) = 1;
+ if (allsimple)
+ TREE_STATIC (result) = 1;
+ }
return result;
}