diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/ChangeLog.tree-ssa | 566 | ||||
-rw-r--r-- | gcc/cp/Make-lang.in | 14 | ||||
-rw-r--r-- | gcc/cp/call.c | 20 | ||||
-rw-r--r-- | gcc/cp/class.c | 31 | ||||
-rw-r--r-- | gcc/cp/cp-lang.c | 121 | ||||
-rw-r--r-- | gcc/cp/cp-mudflap.c | 108 | ||||
-rw-r--r-- | gcc/cp/cp-simplify.c | 236 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 9 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 19 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 5 | ||||
-rw-r--r-- | gcc/cp/decl.c | 89 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 17 | ||||
-rw-r--r-- | gcc/cp/error.c | 12 | ||||
-rw-r--r-- | gcc/cp/except.c | 110 | ||||
-rw-r--r-- | gcc/cp/expr.c | 18 | ||||
-rw-r--r-- | gcc/cp/init.c | 137 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 1 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 5 | ||||
-rw-r--r-- | gcc/cp/parser.c | 22 | ||||
-rw-r--r-- | gcc/cp/pt.c | 37 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 23 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 220 | ||||
-rw-r--r-- | gcc/cp/tree.c | 131 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 67 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 9 |
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; } |