diff options
408 files changed, 9338 insertions, 2118 deletions
diff --git a/ChangeLog.melt b/ChangeLog.melt index 784cc14cbe7..72c68b3c0b1 100644 --- a/ChangeLog.melt +++ b/ChangeLog.melt @@ -1,3 +1,6 @@ +2008-07-08 Basile Starynkevitch <basile@starynkevitch.net> + MELT branch merged with trunk r137620 + 2008-07-02 Basile Starynkevitch <basile@starynkevitch.net> MELT branch merged with trunk r137357 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 916d1b0244a..4a126ecef43 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,555 @@ +2008-07-08 Martin Jambor <mjambor@suse.cz> + + * ipa-cp.c (ipcp_init_cloned_node): Call ipa_check_create_node_params + instead of ipa_create_node_params. + (ipcp_driver): Allocate infos with ipa_check_create_node_params and + ipa_check_create_edge_args, free them with + free_all_ipa_structures_after_ipa_cp, call ipa_register_cgraph_hooks. + + * ipa-prop.c: Include flags.h and tree-inline.h. + (ipa_node_params_vector): New variable. + (ipa_edge_args_vector): New variable. + (edge_removal_hook_holder): New variable. + (node_removal_hook_holder): New variable. + (edge_duplication_hook_holder): New variable. + (node_duplication_hook_holder): New variable. + (ipa_detect_param_modifications): Check for presence of modified flags. + (ipa_compute_jump_functions): Check for presence of jump functions. + (ipa_free_edge_args_substructures): New function. + (ipa_create_node_params): Removed. + (ipa_free_all_edge_args): Changed to deallocate the on-the-side vector. + (ipa_free_node_params_substructures): New function. + (ipa_free_all_node_params): Changed to deallocate the on-the-side + vector. + (ipa_edge_removal_hook): New function. + (ipa_node_removal_hook): New function. + (duplicate_array): New function. + (ipa_edge_duplication_hook): New function. + (ipa_node_duplication_hook): New function. + (ipa_register_cgraph_hooks): New function. + (ipa_unregister_cgraph_hooks): New function. + (free_all_ipa_structures_after_ipa_cp): New function. + + * ipa-prop.h: Include vec.h. + (ipa_node_params_t): New typedef with vector types for it. + (ipa_edge_args_t): New typedef with vector types for it. + (IPA_NODE_REF): Changed to access an on-the-side vector. + (IPA_EDGE_REF): Changed to access an on-the-side vector. + (ipa_check_create_node_params): New function. + (ipa_check_create_edge_args): New function. + + * Makefile.in (IPA_PROP_H): New variable for ipa-prop.h. Converted + all users. + +2008-07-07 Tom Tromey <tromey@redhat.com> + + * configure, config.in: Rebuilt. + * configure.ac: Don't check for scandir or alphasort. + +2008-07-07 Joseph Myers <joseph@codesourcery.com> + + * config/arm/arm.c (arm_init_neon_builtins): Register built-in + types immediately after creating them. + +2008-07-07 Joseph Myers <joseph@codesourcery.com> + + * config/arm/aout.h (DOLLARS_IN_IDENTIFIERS): Remove. + +2008-07-07 Fernando Pereira <fernando@cs.ucla.edu> + + * tree-ssa-structalias.c (compute_points_to_sets): Add call to + dump_constraint_graph. + (dump_constraint_edge): New function. + (dump_constraint_graph): New function. + (debug_constraint_graph): New function. + (dump_constraint): Removed useless comparison. + * tree-ssa-structalias.h (dump_constraint_edge): Declare. + (dump_constraint_graph): Declare. + (debug_constraint_graph): Declare. + * tree-dump.c (struct dump_option_value_info): Declare + TDF_GRAPH. + +2008-07-07 Kai Tietz <kai.tietz@onevision.com> + + * config/i386/i386.c (is_va_list_char_pointer): New. + (ix86_va_start): Replace compare with ms_va_list_type_node + by is_va_list_char_pointer. + (ix86_gimplify_va_arg): Likewise. + +2008-07-07 Martin Jambor <mjambor@suse.cz> + + * cgraph.c (cgraph_edge_max_uid): New variable. + (struct cgraph_edge_hook_list): New type. + (struct cgraph_node_hook_list): New type. + (struct cgraph_2edge_hook_list): New type. + (struct cgraph_2node_hook_list): New type. + (first_cgraph_edge_removal_hook): New variable. + (first_cgraph_node_removal_hook): New variable. + (first_cgraph_edge_duplicated_hook): New variable. + (first_cgraph_node_duplicated_hook): New variable. + (cgraph_add_edge_removal_hook): New function. + (cgraph_remove_edge_removal_hook): New function. + (cgraph_call_edge_removal_hooks): New function. + (cgraph_add_node_removal_hook): New function. + (cgraph_remove_node_removal_hook): New function. + (cgraph_call_node_removal_hooks): New function. + (cgraph_add_edge_duplication_hook): New function. + (cgraph_remove_edge_duplication_hook): New function. + (cgraph_call_edge_duplication_hooks): New function. + (cgraph_add_node_duplication_hook): New function. + (cgraph_remove_node_duplication_hook): New function. + (cgraph_call_node_duplication_hooks): New function. + (cgraph_create_edge): Assign to edge uid. + (cgraph_remove_edge): Call edge removal hooks. + (cgraph_node_remove_callees): Call edge removal hooks. + (cgraph_node_remove_callers): Call edge removal hooks. + (cgraph_remove_node): Call node removal hooks. + (cgraph_clone_edge): Call edge duplication hooks. + (cgraph_clone_node): Call node duplication hooks. + + * cgraph.h (cgraph_edge): New field uid. + (cgraph_edge_hook): New type. + (cgraph_node_hook): New type. + (cgraph_2edge_hook): New type. + (cgraph_2node_hook): New type. + +2008-07-07 Andreas Tobler <a.tobler@schweiz.org> + + * config.in: Regenerate. + +2008-07-07 Vladimir Prus <vladimir@codesourcery.com> + + * gcc.c (print_sysroot): New. + (option_map, display_help, process_command): Handle the + -print-sysroot option. + (main): Print the sysroot if requested. + * doc/invoke.texi (Debugging Options): Document -print-sysroot. + +2008-07-07 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + PR target/34780 + * unwind-pe.h (size_of_encoded_value): add attribute unused. + +2008-07-07 Daniel Jacobowitz <dan@codesourcery.com> + + * function.c (assign_parm_remove_parallels): Check mode of + entry_parm. + (assign_parm_setup_block_p): Also check mode of entry_parm. + +2008-07-07 Richard Guenther <rguenther@suse.de> + + * tree-ssa-structalias.h (set_used_smts): Remove. + * tree-ssa-structalias.c (used_smts): Likewise. + (set_used_smts): Likewise. + * tree-ssa-alias.c (compute_flow_sensitive_aliasing): Remove + call to set_used_smts. + +2008-07-07 Richard Guenther <rguenther@suse.de> + + * tree-ssa-structalias.c (struct variable_info): Add is_full_var flag. + (new_var_info): Set it to false. + (solution_set_add): Correctly handle pointers outside a var and + inside a field. + (type_safe): Treat variables with is_full_var properly. + (do_sd_constraint): Likewise. + (do_ds_constraint): Likewise. + (process_constraint): Remove zeroing offset for !use_field_sensitive. + (get_constraint_for_ptr_offset): New function. + (get_constraint_for_component_ref): For addresses at least include + the last field of the variable. Handle is_full_vars properly. + (get_constraint_for_1): Factor common code, handle POINTER_PLUS_EXPR. + (handle_ptr_arith): Remove. + (find_func_aliases): Simplify assignment handling. + (create_function_info_for): For parameter and result varinfos set + is_full_var flag. + (create_variable_info_for): Set is_full_var flag whenever we + just created a single varinfo for a decl. + (init_alias_vars): Initialize use_field_sensitive from + max-fields-for-field-sensitive parameter. + +2008-07-07 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/36713 + * tree-flow-inline.h (is_call_used): New function. + * tree-nrv.c (dest_safe_for_nrv_p): Use it. + * tree-tailcall.c (suitable_for_tail_opt_p): Likewise. + * tree-outof-ssa.c (create_temp): Set call-used flag if required. + +2008-07-07 Maxim Kuvyrkov <maxim@codesourcery.com> + + * config/m68k/m68k.c (m68k_return_in_memory): Fix arguments types. + +2008-07-07 Mark Shinwell <shinwell@codesourcery.com> + + * config/m68k/lb1sf68.asm: Add PIC macros for Linux targets. + +2008-07-07 Maxim Kuvyrkov <maxim@codesourcery.com> + Nathan Sidwell <nathan@codesourcery.com> + + * config.gcc (m68k-*-linux*): Add with_arch. Add sysroot-suffix.h + to tm_file. Add m68k/t-floatlib, m68k/t-linux & m68k/t-mlibs to + tmake_file. + * config/m68k/t-linux: New. + * doc/install.texi: Document m68k-*-linux is now multilibbed by + default. + +2008-07-07 Nathan Sidwell <nathan@codesourcery.com> + + * config/m68k/t-cf (MULTILIB_EXTRA_OPTS): Add no-mac. + * config/m68k/m68k-devices.def: Remove multilibs that only differ + by MAC/EMAC. + +2008-07-06 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * gcc.c (execute): Fix -Wc++-compat warning. + +2008-07-06 H.J. Lu <hongjiu.lu@intel.com> + + PR target/36720 + * config/ia64/ia64.c (ia64_split_tmode): Fix typo in TImode + constant for little endian. + +2008-07-06 Richard Sandiford <rdsandiford@googlemail.com> + + * config/mips/mips.h (TARGET_CPU_CPP_BUILTINS): Check + mips_base_mips16 instead of TARGET_MIPS16. + (mips_base_mips16): Declare. + * config/mips/mips.c (mips_base_mips16): Make global. + (was_mips16_p): Remove GTY marker. + (was_mips16_pch_p): New variable. + (mips_set_mips16_mode): Check both was_mips16_p and was_mips16_pch_p. + (mips_override_options): Force to non-MIPS16 mode initially. + Do not complain about MIPS16 PIC incompatibilities here. + Only allow -mgpopt if -mexplicit-relocs is in force for + non-MIPS16 code. + +2008-07-06 Andreas Tobler <a.tobler@schweiz.org> + + * configure.ac: Check for caddr_t, define to char * if not defined. + * configure: Regenerate. + * ggc-common.c (mmap_gt_pch_get_address): Fix -Wc++-compat warnings. + (mmap_gt_pch_use_address): Likewise. + * config/host-solaris.c (sol_gt_pch_use_address): Likewise. + +2008-07-06 Richard Guenther <rguenther@suse.de> + + * tree-ssa-structalias.c (struct variable_info): Remove has_union. + (new_var_info): Deal with it. + (solution_set_add): Likewise. + (bitpos_of_field): Make signed, fix. + (struct fieldoff): Remove type and decl fields. Make size field + unsigned HOST_WIDE_INT. Add has_unknown_size and may_have_pointers + flags. + (fieldoff_compare): Deal with it. + (push_fields_onto_fieldstack): Remove has_union argument, glob + adjacent non-pointer fields together. + (create_function_info_for): Do not set has_union. + (create_variable_info_for): Simplify. + +2008-07-06 Kai Tietz <kai.tietz@onevision.com> + + * config.gcc (extra_headers): Add cross-stdarg.h for target + x86_64-*-* and i?86-*-*. + * config/i386/cross-stdarg.h: New. + * builtins.c (std_fn_abi_va_list): New. + (std_canonical_va_list_type): New. + (stabilize_va_list): Replace va_list_type_node use by + mtarget.canonical_va_list_type. + (gimplify_va_arg_expr): Likewise. + (expand_builtin_va_copy): Replace va_list_type_node use by + mtarget.fn_abi_va_list. + * tree-sra.c (is_va_list_type): New helper. + (decl_can_be_decomposed_p): Replace + va_list_type_node use by is_va_list_type. + * tree-ssa-ccp.c (optimize_stdarg_builtin): Likewise. + * tree-stdarg.c (execute_optimize_stdarg): Likewise. + * c-common.c (c_common_nodes_and_builtins): Use TARGET_ENUM_VA_LIST. + * config/i386/i386-protos.h (ix86_get_valist_type): New. + (ix86_enum_va_list): New. + * config/i386/i386.c (sysv_va_list_type_node): New. + (ms_va_list_type_node): New. + (ix86_function_type_abi): Remove sorry. + (ix86_build_builtin_va_list_abi): New. + (ix86_build_builtin_va_list): Call ix86_build_builtin_va_list_abi + for 64-bit targets. + (ix86_va_start): Replace va_list_type_node by sysv_va_list_type_node. + (ix86_init_builtins_va_builtins_abi): New. + (ix86_init_builtins): Use ix86_init_builtins_va_builtins_abi + for 64-bit targets. + (ix86_handle_abi_attribute): New. + (attribute_spec): Add sysv_abi and ms_abi. + (ix86_fn_abi_va_list): New. + (ix86_canonical_va_list_type): New. + (ix86_enum_va_list): New. + (TARGET_FN_ABI_VA_LIST): New. + (TARGET_CANONICAL_VA_LIST_TYPE): New. + * config/i386/i386.h (TARGET_ENUM_VA_LIST): New. + * doc/tm.texi (TARGET_FN_ABI_VA_LIST): New. + (TARGET_CANONICAL_VA_LIST_TYPE): New. + (TARGET_ENUM_VA_LIST): New. + * expr.h (std_fn_abi_va_list): New. + (std_canonical_va_list_type): New. + * target-def.h (TARGET_FN_ABI_VA_LIST): New. + (TARGET_CANONICAL_VA_LIST_TYPE): New. + (TARGET_INITIALIZER): Add TARGET_FN_ABI_VA_LIST and + TARGET_CANONICAL_VA_LIST_TYPE. + * target.h (struct gcc_target): Add fn_abi_va_list hook + and canonical_va_list_type hook. + +2008-07-05 Andrew Pinski <andrew_pinski@playstation.sony.com> + + * fold-const.c (fold_convert_const): Treat OFFSET_TYPE the same as + integral and pointer types. + +2008-07-04 Roger Sayle <roger@eyesopen.com> + + * config/rs6000/host-darwin.c (darwin_rs6000_extra_siganls): Cast + the "void*" result of xmalloc to "char*" to fix bootstrap breakage. + +2008-07-04 Kaz Kojima <kkojima@gcc.gnu.org> + + PR target/36684 + * config/sh/sh.h (OVERRIDE_OPTIONS): Disable -fschedule-insns + for PIC. + +2008-07-04 Jakub Jelinek <jakub@redhat.com> + + * tree-switch-conversion.c (build_one_array, gen_def_assigns): Use + build_gimple_modify_stmt. + (build_arrays, gen_inbound_check): Likewise. Force RHS to be + gimple operand. Use fold_build* instead of build*. + +2008-07-04 Richard Guenther <rguenther@suse.de> + + * tree-ssa-structalias.c (lookup_vi_for_tree): Declare. + (do_sd_constraint): Handle a dereference of ESCAPED and CALLUSED + properly to compute the reachability set if we do field-sensitive PTA. + * invoke.texi (max-fields-for-field-sensitive): Document default. + * opts.c (decode_options): Set max-fields-for-field-sensitive to + 100 for optimize >= 2. + +2008-07-04 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * ggc-zone.c (lookup_page_table_if_allocated, + set_page_table_entry, zone_find_object_size, alloc_small_page, + alloc_large_page, ggc_free, gt_ggc_m_S, ggc_marked_p, init_ggc, + new_ggc_zone, init_ggc_pch, ggc_pch_this_base, ggc_pch_read): Fix + -Wc++-compat and/or -Wcast-qual warnings. + +2008-07-04 Alan Modra <amodra@bigpond.net.au> + + PR target/36634 + * config/rs6000/rs6000.md (call, call_value): Don't arrange for + pic_offset_table_rtx to be marked as used here. + (call_nonlocal_sysv, call_value_nonlocal_sysv): Add split for + TARGET_SECURE_PLT to "use" pic_offset_table_rtx. + (call_nonlocal_sysv_secure, call_value_nonlocal_sysv_secure): New insn. + (sibcall_nonlocal_sysv, sibcall_value_nonlocal_sysv): Assert + !TARGET_SECURE_PLT. + +2008-07-03 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> + + * alloc-pool.c (hash_descriptor, eq_descriptor, + alloc_pool_descriptor): Fix -Wc++-compat warnings. + * bitmap.c (hash_descriptor, eq_descriptor, bitmap_descriptor): + Likewise. + * ggc-common.c (hash_descriptor, eq_descriptor, hash_ptr, eq_ptr, + loc_descriptor, ggc_prune_ptr, ggc_free_overhead, + final_cmp_statistic, cmp_statistic, dump_ggc_loc_statistics): + Likewise. + * varray.c (hash_descriptor, eq_descriptor, varray_descriptor): + Likewise. + +2008-07-03 Eric Botcazou <ebotcazou@adacore.com> + + * tree-flow.h (loop_only_exit_p): Declare. + * tree-ssa-loop-niter.c (loop_only_exit_p): Make public. + * tree-ssa-loop-ivopts.c (may_eliminate_iv): Reinstate direct check on + the number of iterations if it is constant. Otherwise, if this is the + only possible exit of the loop, use the conservative estimate on the + number of iterations of the entire loop if available. + +2008-07-03 Richard Sandiford <rdsandiford@googlemail.com> + + * Makefile.in (libgcc.mvars): Add LIBGCC_SYNC and LIBGCC_SYNC_CFLAGS. + * libgcc-std.ver (GCC_4.4.0): New version, inherited from GCC_4.3.0. + Add synchronization functions. + * config/sync.c: New file. + * config/mips/t-libgcc-mips16 (LIBGCC_SYNC): Define. + (LIBGCC_SYNC_CFLAGS): Likewise. + +2008-07-03 Uros Bizjak <ubizjak@gmail.com> + + PR target/36710 + * config/i386/i386.md (mode): Add TF to "mode" attribute. + (*pushtf_sse): New insn pattern. + (pushtf splitters): New splitters. + +2008-07-03 Michael Meissner <gnu@the-meissners.org> + + PR middle-end/35736 + * predict.c (build_predict_expr): Use void_type_node for the tree + type, instead of NULL_TREE. + +2008-07-03 H.J. Lu <hongjiu.lu@intel.com> + + * config/i386/i386.c (contains_aligned_value_p): Return true + for TCmode. + (ix86_data_alignment): Align TCmode to 128bits. + (ix86_local_alignment): Likewise. + +2008-07-03 Andrew Haley <aph@redhat.com> + + PR bootstrap/33304 + * vec.h (VEC_TA): New. + (DEF_VEC_I, DEF_VEC_P, DEF_VEC_ALLOC_I, DEF_VEC_ALLOC_P, + DEF_VEC_O, DEF_VEC_ALLOC_O: Use VEC_TA. + * c-common.c (C_COMMON_FIXED_TYPES_SAT): New macro. + (C_COMMON_FIXED_MODE_TYPES_SAT): New macro. + (C_COMMON_FIXED_TYPES): Remove first arg. + (C_COMMON_FIXED_MODE_TYPES): Likewise. + * tree.c (MAKE_FIXED_TYPE_NODE): Break into two macros, + MAKE_FIXED_TYPE_NODE and MAKE_FIXED_TYPE_NODE_WIDTH in order + not to use empty macro arguments. + +2008-07-02 Joseph Myers <joseph@codesourcery.com> + + * config/alpha/vms_tramp.asm, config/arm/crti.asm, + config/arm/crtn.asm, config/bfin/crti.s, config/bfin/crtlibid.s, + config/bfin/crtn.s, config/fr30/crti.asm, config/fr30/crtn.asm, + config/frv/lib1funcs.asm, config/i386/sol2-c1.asm, + config/i386/sol2-ci.asm, config/i386/sol2-cn.asm, + config/i386/sol2-gc1.asm, config/ia64/crti.asm, + config/ia64/crtn.asm, config/m68hc11/larith.asm, + config/m68hc11/m68hc11-crt0.S, config/m68k/crti.s, + config/m68k/crtn.s, config/mcore/crti.asm, config/mcore/crtn.asm, + config/rs6000/crtresfpr.asm, config/rs6000/crtresgpr.asm, + config/rs6000/crtresxfpr.asm, config/rs6000/crtresxgpr.asm, + config/rs6000/crtsavfpr.asm, config/rs6000/crtsavgpr.asm, + config/rs6000/crtsavres.asm, config/rs6000/e500crtres32gpr.asm, + config/rs6000/e500crtres64gpr.asm, + config/rs6000/e500crtres64gprctr.asm, + config/rs6000/e500crtrest32gpr.asm, + config/rs6000/e500crtrest64gpr.asm, + config/rs6000/e500crtresx32gpr.asm, + config/rs6000/e500crtresx64gpr.asm, + config/rs6000/e500crtsav32gpr.asm, + config/rs6000/e500crtsav64gpr.asm, + config/rs6000/e500crtsav64gprctr.asm, + config/rs6000/e500crtsavg32gpr.asm, + config/rs6000/e500crtsavg64gpr.asm, + config/rs6000/e500crtsavg64gprctr.asm, config/rs6000/eabi-ci.asm, + config/rs6000/eabi-cn.asm, config/rs6000/eabi.asm, + config/rs6000/sol-ci.asm, config/rs6000/sol-cn.asm, + config/rs6000/tramp.asm, config/sparc/sol2-ci.asm, + config/sparc/sol2-cn.asm: Remove .file directives. + +2008-07-02 Richard Sandiford <rdsandiford@googlemail.com> + + * resource.c (mark_referenced_resources): Look inside + UNSPEC_VOLATILEs and ASM_INPUTs. + +2008-07-02 Ian Lance Taylor <iant@google.com> + + * rtlanal.c (add_reg_note): New function. + * rtl.h (add_reg_note): Declare. + * auto-inc-dec.c (attempt_change): Use add_reg_note. + * bb-reorder.c (add_reg_crossing_jump_notes): Likewise. + * builtins.c (expand_builtin_longjmp): Likewise. + (expand_builtin_nonlocal_goto): Likewise. + * calls.c (emit_call_1, expand_call): Likewise. + * cfgexpand.c (add_reg_br_prob_note): Likewise. + * cfglayout.c (fixup_reorder_chain): Likewise. + * cfgrtl.c (force_nonfallthru_and_redirect): Likewise. + (commit_one_edge_insertion): Likewise. + * combine.c (move_deaths, distribute_notes): Likewise. + * df-problems.c (df_set_note): Likewise. + * emit-rtl.c (link_cc0_insns, try_split): Likewise. + (set_unique_reg_note): Likewise. + (emit_copy_of_insn_after): Likewise. + * expr.c (expand_expr_real): Likewise. + * gcse.c (add_label_notes): Likewise. + * haifa-sched.c (create_check_block_twin): Likewise. + * jump.c (mark_jump_label_1): Likewise. + * loop-doloop.c (add_test, doloop_modify): Likewise. + * loop-unswitch.c (compare_and_jump_seq): Likewise. + * lower-subreg.c (move_eh_region_note): Likewise. + * optabs.c (emit_libcall_block): Likewise. + * predict.c (predict_insn): Likewise. + (combine_predictions_for_insn): Likewise. + * recog.c (peephole2_optimize): Likewise. + * regmove.c (try_auto_increment): Likewise. + * reg-stack.c (emit_pop_insn, move_for_stack_reg): Likewise. + * reload.c (find_reloads): Likewise. + * reload1.c (fixup_eh_region_note): Likewise. + (reload_as_needed, add_auto_inc_notes, copy_eh_notes): Likewise. + * reorg.c (delete_prior_computation): Likewise. + (delete_computation, dbr_schedule): Likewise. + * config/pa/pa.c (legitimize_pic_address): Likewise. + * config/sh/sh.c (sh_reorg): Likewise. + +2008-07-02 H.J. Lu <hongjiu.lu@intel.com> + + PR target/36669 + * config/libgcc-glibc.ver: Add %exclude. + * config/m32r/libgcc-glibc.ver: Likwise. + * config/s390/libgcc-glibc.ver: Likwise. + * config/sh/libgcc-glibc.ver: Likwise. + * config/sparc/libgcc-sparc-glibc.ver: Likwise. + + * config/i386/libgcc-glibc.ver: New. + + * config/i386/libgcc-x86_64-glibc.ver: Removed. + +2008-07-02 H.J. Lu <hongjiu.lu@intel.com> + + * config.gcc: Remove i386/t-fprules-softfp64 soft-fp/t-softfp + from tmake_file from i[34567]86-*-darwin*, x86_64-*-darwin*, + i[34567]86-*-linux*, x86_64-*-linux*. Add + i386/t-fprules-softfp and soft-fp/t-softfp to tmake_file for + i[34567]86-*-darwin*, x86_64-*-darwin*, i[34567]86-*-linux*, + x86_64-*-linux*. Add i386/t-linux to tmake_file for + i[34567]86-*-linux*, x86_64-*-linux*. + + * libgcc-std.ver: Add empty GCC_4.4.0. + + * mkmap-symver.awk: Support multiple versions per symbol. + + * config/i386/i386.c (ix86_init_builtins): Always define + __builtin_fabsq and __builtin_copysignq with fallbacks. + (ix86_expand_builtin): Emit normal call for __builtin_fabsq + and __builtin_copysignq if SSE2 isn't available. + + * config/i386/linux.h (LIBGCC2_HAS_TF_MODE): Defined. + (LIBGCC2_TF_CEXT): Likwise. + (TF_SIZE): Likwise. + + * config/i386/linux64.h (LIBGCC2_HAS_TF_MODE): Defined as 1. + + * config/i386/sfp-machine.h: Moved to libgcc. + + * config/i386/sfp-machine.h: New. + * config/i386/t-linux: Likwise. + + * config/i386/t-darwin: Remove softfp_wrap_start and + softfp_wrap_end. + * config/i386/t-darwin64: Likewise. + + * config/i386/t-fprules-softfp64: Renamed to ... + * config/i386/t-fprules-softfp: This. + + * config/i386/t-linux64: Remove SHLIB_MAPFILES, softfp_wrap_start + and softfp_wrap_end. + +2008-07-02 Jason Merrill <jason@redhat.com> + + * tree.c (ctor_to_list): Use FOR_EACH_CONSTRUCTOR_ELT. + + * tree.c (ctor_to_list): New fn. + * tree.h: Declare it. + (CONSTRUCTOR_ELT): New macro. + (CONSTRUCTOR_NELTS): New macro. + 2008-07-02 Richard Guenther <rguenther@suse.de> * tree-ssa-structalias.c (struct variable_info): Reorder @@ -127,19 +679,19 @@ 2008-07-01 Martin Jambor <mjambor@suse.cz> - * Makefile.in (tree-switch-conversion.o): Add. - (OBJS-common): Add tree-swtch-conversion.o. - * passes.c (init_optimization_passes): Add pass_convert_switch. - * tree-pass.h: (pass_convert_switch): Add. - * tree-switch-conversion.c: New file. - * gcc.dg/tree-ssa/cswtch.c: New testcase. - * common.opt (ftree-cswtch): New option. - * params.h (PARAM_SWITCH_CONVERSION_BRANCH_RATIO): New parameter. - * params.def (PARAM_SWITCH_CONVERSION_BRANCH_RATIO): New parameter. - * opts.c (decode_options): Set flag_tree_switch_conversion when - optimization level is >= 2. - * doc/invoke.texi (Optimize Options): Added description of - -ftree-swtch-conversion and switch-conversion-max-branch-ratio. + * Makefile.in (tree-switch-conversion.o): Add. + (OBJS-common): Add tree-swtch-conversion.o. + * passes.c (init_optimization_passes): Add pass_convert_switch. + * tree-pass.h: (pass_convert_switch): Add. + * tree-switch-conversion.c: New file. + * gcc.dg/tree-ssa/cswtch.c: New testcase. + * common.opt (ftree-cswtch): New option. + * params.h (PARAM_SWITCH_CONVERSION_BRANCH_RATIO): New parameter. + * params.def (PARAM_SWITCH_CONVERSION_BRANCH_RATIO): New parameter. + * opts.c (decode_options): Set flag_tree_switch_conversion when + optimization level is >= 2. + * doc/invoke.texi (Optimize Options): Added description of + -ftree-swtch-conversion and switch-conversion-max-branch-ratio. 2008-06-30 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> @@ -159,7 +711,7 @@ PR rtl-optimization/34744 * df-scan.c (df_scan_free_ref_vec, df_scan_free_mws_vec): New macros. - (df_scan_free_internal): Free data structures not + (df_scan_free_internal): Free data structures not allocated in storage pools. (df_mw_hardreg_chain_delete_eq_uses): Use df_scan_free_mws_vec. (df_refs_add_to_chains): Use df_scan_free_ref_vec and diff --git a/gcc/ChangeLog.melt b/gcc/ChangeLog.melt index 9dffa5b07dc..f69ec5ba2a3 100644 --- a/gcc/ChangeLog.melt +++ b/gcc/ChangeLog.melt @@ -1,4 +1,7 @@ 2008-07-08 Basile Starynkevitch <basile@starynkevitch.net> + MELT branch merged with trunk r137620 + +2008-07-08 Basile Starynkevitch <basile@starynkevitch.net> * melt/warmelt-macro.bysl: added mexpand_defciterator expand_citeration and extended macroexpand_1 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index bc40ef40751..9c0637d2a77 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20080702 +20080708 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 2688eed189b..4dff4b7b074 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -862,6 +862,7 @@ TREE_INLINE_H = tree-inline.h $(VARRAY_H) pointer-set.h REAL_H = real.h $(MACHMODE_H) DBGCNT_H = dbgcnt.h dbgcnt.def EBIMAP_H = ebitmap.h sbitmap.h +IPA_PROP_H = $(TREE_H) vec.h # # Now figure out from those variables how to compile and link. @@ -1704,6 +1705,8 @@ libgcc.mvars: config.status Makefile $(LIB2ADD) $(LIB2ADD_ST) specs \ echo SHLIB_MAPFILES = '$(call srcdirify,$(SHLIB_MAPFILES))' >> tmp-libgcc.mvars echo SHLIB_NM_FLAGS = '$(SHLIB_NM_FLAGS)' >> tmp-libgcc.mvars echo LIBGCC2_CFLAGS = '$(LIBGCC2_CFLAGS)' >> tmp-libgcc.mvars + echo LIBGCC_SYNC = '$(LIBGCC_SYNC)' >> tmp-libgcc.mvars + echo LIBGCC_SYNC_CFLAGS = '$(LIBGCC_SYNC_CFLAGS)' >> tmp-libgcc.mvars echo CRTSTUFF_CFLAGS = '$(CRTSTUFF_CFLAGS)' >> tmp-libgcc.mvars echo CRTSTUFF_T_CFLAGS = '$(CRTSTUFF_T_CFLAGS)' >> tmp-libgcc.mvars echo CRTSTUFF_T_CFLAGS_S = '$(CRTSTUFF_T_CFLAGS_S)' >> tmp-libgcc.mvars @@ -2045,7 +2048,7 @@ tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \ langhooks.h $(TREE_INLINE_H) $(CGRAPH_H) intl.h $(FUNCTION_H) $(TREE_GIMPLE_H) \ debug.h $(DIAGNOSTIC_H) $(TREE_FLOW_H) tree-iterator.h tree-mudflap.h \ - ipa-prop.h value-prof.h $(TARGET_H) $(INTEGRATE_H) + $(IPA_PROP_H) value-prof.h $(TARGET_H) $(INTEGRATE_H) print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(GGC_H) langhooks.h $(REAL_H) tree-iterator.h fixed-value.h $(TREE_FLOW_H) stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ @@ -2582,7 +2585,7 @@ cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(FLAGS_H) $(GGC_H) \ $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(TREE_GIMPLE_H) \ $(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \ - $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) ipa-prop.h \ + $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) $(IPA_PROP_H) \ gt-cgraphunit.h cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h $(CGRAPH_H) intl.h pointer-set.h $(TREE_GIMPLE_H) \ @@ -2591,14 +2594,14 @@ varpool.o : varpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(FLAGS_H) $(GGC_H) \ $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(TREE_GIMPLE_H) \ $(TREE_FLOW_H) tree-pass.h $(C_COMMON_H) debug.h $(DIAGNOSTIC_H) \ - $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) ipa-prop.h \ + $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) $(IPA_PROP_H) \ gt-varpool.h ipa.o : ipa.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(CGRAPH_H) ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) ipa-prop.h \ - $(TREE_FLOW_H) $(TM_H) tree-pass.h $(FLAGS_H) $(TREE_H) + langhooks.h $(GGC_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) \ + $(TREE_FLOW_H) $(TM_H) tree-pass.h $(FLAGS_H) $(TREE_H) tree-inline.h ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - langhooks.h $(TARGET_H) $(CGRAPH_H) ipa-prop.h tree-inline.h tree-dump.h \ + langhooks.h $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) tree-inline.h tree-dump.h \ $(TREE_FLOW_H) $(TM_H) tree-pass.h $(FLAGS_H) $(TREE_H) $(DIAGNOSTIC_H) matrix-reorg.o : matrix-reorg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TARGET_H) $(CGRAPH_H) $(TREE_FLOW_H) $(TM_H) tree-pass.h \ diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c index b22869fe787..7f0dc8ce7d2 100644 --- a/gcc/alloc-pool.c +++ b/gcc/alloc-pool.c @@ -81,13 +81,15 @@ static htab_t alloc_pool_hash; static hashval_t hash_descriptor (const void *p) { - const struct alloc_pool_descriptor *d = p; + const struct alloc_pool_descriptor *const d = + (const struct alloc_pool_descriptor * )p; return htab_hash_pointer (d->name); } static int eq_descriptor (const void *p1, const void *p2) { - const struct alloc_pool_descriptor *d = p1; + const struct alloc_pool_descriptor *const d = + (const struct alloc_pool_descriptor *) p1; return d->name == p2; } @@ -106,7 +108,7 @@ alloc_pool_descriptor (const char *name) 1); if (*slot) return *slot; - *slot = xcalloc (sizeof (**slot), 1); + *slot = XCNEW (struct alloc_pool_descriptor); (*slot)->name = name; return *slot; } diff --git a/gcc/auto-inc-dec.c b/gcc/auto-inc-dec.c index 18c1b7107da..35d6c87a696 100644 --- a/gcc/auto-inc-dec.c +++ b/gcc/auto-inc-dec.c @@ -621,8 +621,7 @@ attempt_change (rtx new_addr, rtx inc_reg) } /* Record that this insn has an implicit side effect. */ - REG_NOTES (mem_insn.insn) - = alloc_EXPR_LIST (REG_INC, inc_reg, REG_NOTES (mem_insn.insn)); + add_reg_note (mem_insn.insn, REG_INC, inc_reg); if (dump_file) { diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index b36c6c24bb3..ae24c0c3245 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -1785,10 +1785,7 @@ add_reg_crossing_jump_notes (void) FOR_EACH_EDGE (e, ei, bb->succs) if ((e->flags & EDGE_CROSSING) && JUMP_P (BB_END (e->src))) - REG_NOTES (BB_END (e->src)) = gen_rtx_EXPR_LIST (REG_CROSSING_JUMP, - NULL_RTX, - REG_NOTES (BB_END - (e->src))); + add_reg_note (BB_END (e->src), REG_CROSSING_JUMP, NULL_RTX); } /* Hot and cold basic blocks are partitioned and put in separate diff --git a/gcc/bitmap.c b/gcc/bitmap.c index 4fabdc915d2..5e841e067a5 100644 --- a/gcc/bitmap.c +++ b/gcc/bitmap.c @@ -51,7 +51,8 @@ static htab_t bitmap_desc_hash; static hashval_t hash_descriptor (const void *p) { - const struct bitmap_descriptor *const d = p; + const struct bitmap_descriptor *const d = + (const struct bitmap_descriptor *) p; return htab_hash_pointer (d->file) + d->line; } struct loc @@ -63,8 +64,9 @@ struct loc static int eq_descriptor (const void *p1, const void *p2) { - const struct bitmap_descriptor *const d = p1; - const struct loc *const l = p2; + const struct bitmap_descriptor *const d = + (const struct bitmap_descriptor *) p1; + const struct loc *const l = (const struct loc *) p2; return d->file == l->file && d->function == l->function && d->line == l->line; } @@ -88,7 +90,7 @@ bitmap_descriptor (const char *file, const char *function, int line) 1); if (*slot) return *slot; - *slot = xcalloc (sizeof (**slot), 1); + *slot = XCNEW (struct bitmap_descriptor); (*slot)->file = file; (*slot)->function = function; (*slot)->line = line; diff --git a/gcc/builtins.c b/gcc/builtins.c index 10af34254aa..2d6ad2a1a34 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -845,8 +845,7 @@ expand_builtin_longjmp (rtx buf_addr, rtx value) if (JUMP_P (insn)) { - REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, const0_rtx, - REG_NOTES (insn)); + add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx); break; } else if (CALL_P (insn)) @@ -929,8 +928,7 @@ expand_builtin_nonlocal_goto (tree exp) { if (JUMP_P (insn)) { - REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO, - const0_rtx, REG_NOTES (insn)); + add_reg_note (insn, REG_NON_LOCAL_GOTO, const0_rtx); break; } else if (CALL_P (insn)) @@ -4625,18 +4623,22 @@ expand_builtin_next_arg (void) static tree stabilize_va_list (tree valist, int needs_lvalue) { - if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) + tree vatype = targetm.canonical_va_list_type (TREE_TYPE (valist)); + + gcc_assert (vatype != NULL_TREE); + + if (TREE_CODE (vatype) == ARRAY_TYPE) { if (TREE_SIDE_EFFECTS (valist)) valist = save_expr (valist); /* For this case, the backends will be expecting a pointer to - TREE_TYPE (va_list_type_node), but it's possible we've - actually been given an array (an actual va_list_type_node). + vatype, but it's possible we've actually been given an array + (an actual TARGET_CANONICAL_VA_LIST_TYPE (valist)). So fix it. */ if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) { - tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node)); + tree p1 = build_pointer_type (TREE_TYPE (vatype)); valist = build_fold_addr_expr_with_type (valist, p1); } } @@ -4649,7 +4651,7 @@ stabilize_va_list (tree valist, int needs_lvalue) if (! TREE_SIDE_EFFECTS (valist)) return valist; - pt = build_pointer_type (va_list_type_node); + pt = build_pointer_type (vatype); valist = fold_build1 (ADDR_EXPR, pt, valist); TREE_SIDE_EFFECTS (valist) = 1; } @@ -4670,6 +4672,47 @@ std_build_builtin_va_list (void) return ptr_type_node; } +/* The "standard" abi va_list is va_list_type_node. */ + +tree +std_fn_abi_va_list (tree fndecl ATTRIBUTE_UNUSED) +{ + return va_list_type_node; +} + +/* The "standard" type of va_list is va_list_type_node. */ + +tree +std_canonical_va_list_type (tree type) +{ + tree wtype, htype; + + if (INDIRECT_REF_P (type)) + type = TREE_TYPE (type); + else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type))) + type = TREE_TYPE (type); + + wtype = va_list_type_node; + htype = type; + if (TREE_CODE (wtype) == ARRAY_TYPE) + { + /* If va_list is an array type, the argument may have decayed + to a pointer type, e.g. by being passed to another function. + In that case, unwrap both types so that we can compare the + underlying records. */ + if (TREE_CODE (htype) == ARRAY_TYPE + || POINTER_TYPE_P (htype)) + { + wtype = TREE_TYPE (wtype); + htype = TREE_TYPE (htype); + } + } + if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype)) + return va_list_type_node; + + return NULL_TREE; +} + /* The "standard" implementation of va_start: just assign `nextarg' to the variable. */ @@ -4825,33 +4868,18 @@ dummy_object (tree type) enum gimplify_status gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p) { - tree promoted_type, want_va_type, have_va_type; + tree promoted_type, have_va_type; tree valist = TREE_OPERAND (*expr_p, 0); tree type = TREE_TYPE (*expr_p); tree t; /* Verify that valist is of the proper type. */ - want_va_type = va_list_type_node; have_va_type = TREE_TYPE (valist); - if (have_va_type == error_mark_node) return GS_ERROR; + have_va_type = targetm.canonical_va_list_type (have_va_type); - if (TREE_CODE (want_va_type) == ARRAY_TYPE) - { - /* If va_list is an array type, the argument may have decayed - to a pointer type, e.g. by being passed to another function. - In that case, unwrap both types so that we can compare the - underlying records. */ - if (TREE_CODE (have_va_type) == ARRAY_TYPE - || POINTER_TYPE_P (have_va_type)) - { - want_va_type = TREE_TYPE (want_va_type); - have_va_type = TREE_TYPE (have_va_type); - } - } - - if (TYPE_MAIN_VARIANT (want_va_type) != TYPE_MAIN_VARIANT (have_va_type)) + if (have_va_type == NULL_TREE) { error ("first argument to %<va_arg%> not of type %<va_list%>"); return GS_ERROR; @@ -4859,7 +4887,7 @@ gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p) /* Generate a diagnostic for requesting data of a type that cannot be passed through `...' due to type promotion at the call site. */ - else if ((promoted_type = lang_hooks.types.type_promotes_to (type)) + if ((promoted_type = lang_hooks.types.type_promotes_to (type)) != type) { static bool gave_help; @@ -4891,15 +4919,15 @@ gimplify_va_arg_expr (tree *expr_p, tree *pre_p, tree *post_p) { /* Make it easier for the backends by protecting the valist argument from multiple evaluations. */ - if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) + if (TREE_CODE (have_va_type) == ARRAY_TYPE) { /* For this case, the backends will be expecting a pointer to - TREE_TYPE (va_list_type_node), but it's possible we've - actually been given an array (an actual va_list_type_node). + TREE_TYPE (abi), but it's possible we've + actually been given an array (an actual TARGET_FN_ABI_VA_LIST). So fix it. */ if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) { - tree p1 = build_pointer_type (TREE_TYPE (va_list_type_node)); + tree p1 = build_pointer_type (TREE_TYPE (have_va_type)); valist = build_fold_addr_expr_with_type (valist, p1); } gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue); @@ -4947,9 +4975,11 @@ expand_builtin_va_copy (tree exp) dst = stabilize_va_list (dst, 1); src = stabilize_va_list (src, 0); - if (TREE_CODE (va_list_type_node) != ARRAY_TYPE) + gcc_assert (cfun != NULL && cfun->decl != NULL_TREE); + + if (TREE_CODE (targetm.fn_abi_va_list (cfun->decl)) != ARRAY_TYPE) { - t = build2 (MODIFY_EXPR, va_list_type_node, dst, src); + t = build2 (MODIFY_EXPR, targetm.fn_abi_va_list (cfun->decl), dst, src); TREE_SIDE_EFFECTS (t) = 1; expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); } @@ -4960,8 +4990,8 @@ expand_builtin_va_copy (tree exp) /* Evaluate to pointers. */ dstb = expand_expr (dst, NULL_RTX, Pmode, EXPAND_NORMAL); srcb = expand_expr (src, NULL_RTX, Pmode, EXPAND_NORMAL); - size = expand_expr (TYPE_SIZE_UNIT (va_list_type_node), NULL_RTX, - VOIDmode, EXPAND_NORMAL); + size = expand_expr (TYPE_SIZE_UNIT (targetm.fn_abi_va_list (cfun->decl)), + NULL_RTX, VOIDmode, EXPAND_NORMAL); dstb = convert_memory_address (Pmode, dstb); srcb = convert_memory_address (Pmode, srcb); @@ -4969,10 +4999,10 @@ expand_builtin_va_copy (tree exp) /* "Dereference" to BLKmode memories. */ dstb = gen_rtx_MEM (BLKmode, dstb); set_mem_alias_set (dstb, get_alias_set (TREE_TYPE (TREE_TYPE (dst)))); - set_mem_align (dstb, TYPE_ALIGN (va_list_type_node)); + set_mem_align (dstb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl))); srcb = gen_rtx_MEM (BLKmode, srcb); set_mem_alias_set (srcb, get_alias_set (TREE_TYPE (TREE_TYPE (src)))); - set_mem_align (srcb, TYPE_ALIGN (va_list_type_node)); + set_mem_align (srcb, TYPE_ALIGN (targetm.fn_abi_va_list (cfun->decl))); /* Copy. */ emit_block_move (dstb, srcb, size, BLOCK_OP_NORMAL); diff --git a/gcc/c-common.c b/gcc/c-common.c index dcae16529fb..9356b8e925e 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -2291,53 +2291,77 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type) if (type1 == intQI_type_node || type1 == unsigned_intQI_type_node) return unsignedp ? unsigned_intQI_type_node : intQI_type_node; -#define C_COMMON_FIXED_TYPES(SAT,NAME) \ - if (type1 == SAT ## short_ ## NAME ## _type_node \ - || type1 == SAT ## unsigned_short_ ## NAME ## _type_node) \ - return unsignedp ? SAT ## unsigned_short_ ## NAME ## _type_node \ - : SAT ## short_ ## NAME ## _type_node; \ - if (type1 == SAT ## NAME ## _type_node \ - || type1 == SAT ## unsigned_ ## NAME ## _type_node) \ - return unsignedp ? SAT ## unsigned_ ## NAME ## _type_node \ - : SAT ## NAME ## _type_node; \ - if (type1 == SAT ## long_ ## NAME ## _type_node \ - || type1 == SAT ## unsigned_long_ ## NAME ## _type_node) \ - return unsignedp ? SAT ## unsigned_long_ ## NAME ## _type_node \ - : SAT ## long_ ## NAME ## _type_node; \ - if (type1 == SAT ## long_long_ ## NAME ## _type_node \ - || type1 == SAT ## unsigned_long_long_ ## NAME ## _type_node) \ - return unsignedp ? SAT ## unsigned_long_long_ ## NAME ## _type_node \ - : SAT ## long_long_ ## NAME ## _type_node; - -#define C_COMMON_FIXED_MODE_TYPES(SAT,NAME) \ - if (type1 == SAT ## NAME ## _type_node \ - || type1 == SAT ## u ## NAME ## _type_node) \ - return unsignedp ? SAT ## u ## NAME ## _type_node \ - : SAT ## NAME ## _type_node; - - C_COMMON_FIXED_TYPES (, fract); - C_COMMON_FIXED_TYPES (sat_, fract); - C_COMMON_FIXED_TYPES (, accum); - C_COMMON_FIXED_TYPES (sat_, accum); - - C_COMMON_FIXED_MODE_TYPES (, qq); - C_COMMON_FIXED_MODE_TYPES (, hq); - C_COMMON_FIXED_MODE_TYPES (, sq); - C_COMMON_FIXED_MODE_TYPES (, dq); - C_COMMON_FIXED_MODE_TYPES (, tq); - C_COMMON_FIXED_MODE_TYPES (sat_, qq); - C_COMMON_FIXED_MODE_TYPES (sat_, hq); - C_COMMON_FIXED_MODE_TYPES (sat_, sq); - C_COMMON_FIXED_MODE_TYPES (sat_, dq); - C_COMMON_FIXED_MODE_TYPES (sat_, tq); - C_COMMON_FIXED_MODE_TYPES (, ha); - C_COMMON_FIXED_MODE_TYPES (, sa); - C_COMMON_FIXED_MODE_TYPES (, da); - C_COMMON_FIXED_MODE_TYPES (, ta); - C_COMMON_FIXED_MODE_TYPES (sat_, ha); - C_COMMON_FIXED_MODE_TYPES (sat_, sa); - C_COMMON_FIXED_MODE_TYPES (sat_, da); - C_COMMON_FIXED_MODE_TYPES (sat_, ta); +#define C_COMMON_FIXED_TYPES(NAME) \ + if (type1 == short_ ## NAME ## _type_node \ + || type1 == unsigned_short_ ## NAME ## _type_node) \ + return unsignedp ? unsigned_short_ ## NAME ## _type_node \ + : short_ ## NAME ## _type_node; \ + if (type1 == NAME ## _type_node \ + || type1 == unsigned_ ## NAME ## _type_node) \ + return unsignedp ? unsigned_ ## NAME ## _type_node \ + : NAME ## _type_node; \ + if (type1 == long_ ## NAME ## _type_node \ + || type1 == unsigned_long_ ## NAME ## _type_node) \ + return unsignedp ? unsigned_long_ ## NAME ## _type_node \ + : long_ ## NAME ## _type_node; \ + if (type1 == long_long_ ## NAME ## _type_node \ + || type1 == unsigned_long_long_ ## NAME ## _type_node) \ + return unsignedp ? unsigned_long_long_ ## NAME ## _type_node \ + : long_long_ ## NAME ## _type_node; + +#define C_COMMON_FIXED_MODE_TYPES(NAME) \ + if (type1 == NAME ## _type_node \ + || type1 == u ## NAME ## _type_node) \ + return unsignedp ? u ## NAME ## _type_node \ + : NAME ## _type_node; + +#define C_COMMON_FIXED_TYPES_SAT(NAME) \ + if (type1 == sat_ ## short_ ## NAME ## _type_node \ + || type1 == sat_ ## unsigned_short_ ## NAME ## _type_node) \ + return unsignedp ? sat_ ## unsigned_short_ ## NAME ## _type_node \ + : sat_ ## short_ ## NAME ## _type_node; \ + if (type1 == sat_ ## NAME ## _type_node \ + || type1 == sat_ ## unsigned_ ## NAME ## _type_node) \ + return unsignedp ? sat_ ## unsigned_ ## NAME ## _type_node \ + : sat_ ## NAME ## _type_node; \ + if (type1 == sat_ ## long_ ## NAME ## _type_node \ + || type1 == sat_ ## unsigned_long_ ## NAME ## _type_node) \ + return unsignedp ? sat_ ## unsigned_long_ ## NAME ## _type_node \ + : sat_ ## long_ ## NAME ## _type_node; \ + if (type1 == sat_ ## long_long_ ## NAME ## _type_node \ + || type1 == sat_ ## unsigned_long_long_ ## NAME ## _type_node) \ + return unsignedp ? sat_ ## unsigned_long_long_ ## NAME ## _type_node \ + : sat_ ## long_long_ ## NAME ## _type_node; + +#define C_COMMON_FIXED_MODE_TYPES_SAT(NAME) \ + if (type1 == sat_ ## NAME ## _type_node \ + || type1 == sat_ ## u ## NAME ## _type_node) \ + return unsignedp ? sat_ ## u ## NAME ## _type_node \ + : sat_ ## NAME ## _type_node; + + C_COMMON_FIXED_TYPES (fract); + C_COMMON_FIXED_TYPES_SAT (fract); + C_COMMON_FIXED_TYPES (accum); + C_COMMON_FIXED_TYPES_SAT (accum); + + C_COMMON_FIXED_MODE_TYPES (qq); + C_COMMON_FIXED_MODE_TYPES (hq); + C_COMMON_FIXED_MODE_TYPES (sq); + C_COMMON_FIXED_MODE_TYPES (dq); + C_COMMON_FIXED_MODE_TYPES (tq); + C_COMMON_FIXED_MODE_TYPES_SAT (qq); + C_COMMON_FIXED_MODE_TYPES_SAT (hq); + C_COMMON_FIXED_MODE_TYPES_SAT (sq); + C_COMMON_FIXED_MODE_TYPES_SAT (dq); + C_COMMON_FIXED_MODE_TYPES_SAT (tq); + C_COMMON_FIXED_MODE_TYPES (ha); + C_COMMON_FIXED_MODE_TYPES (sa); + C_COMMON_FIXED_MODE_TYPES (da); + C_COMMON_FIXED_MODE_TYPES (ta); + C_COMMON_FIXED_MODE_TYPES_SAT (ha); + C_COMMON_FIXED_MODE_TYPES_SAT (sa); + C_COMMON_FIXED_MODE_TYPES_SAT (da); + C_COMMON_FIXED_MODE_TYPES_SAT (ta); /* For ENUMERAL_TYPEs in C++, must check the mode of the types, not the precision; they have precision set to match their range, but @@ -3988,6 +4012,20 @@ c_common_nodes_and_builtins (void) lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"), va_list_type_node)); +#ifdef TARGET_ENUM_VA_LIST + { + int l; + const char *pname; + tree ptype; + for (l = 0; TARGET_ENUM_VA_LIST (l, &pname, &ptype); ++l) + { + lang_hooks.decls.pushdecl + (build_decl (TYPE_DECL, get_identifier (pname), + ptype)); + + } + } +#endif if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) { diff --git a/gcc/calls.c b/gcc/calls.c index 79dc47b98fa..a4470fa1477 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -377,8 +377,7 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED, /* If this call can't throw, attach a REG_EH_REGION reg note to that effect. */ if (ecf_flags & ECF_NOTHROW) - REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, const0_rtx, - REG_NOTES (call_insn)); + add_reg_note (call_insn, REG_EH_REGION, const0_rtx); else { int rn = lookup_stmt_eh_region (fntree); @@ -386,18 +385,15 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED, /* If rn < 0, then either (1) tree-ssa not used or (2) doesn't throw, which we already took care of. */ if (rn > 0) - REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (rn), - REG_NOTES (call_insn)); + add_reg_note (call_insn, REG_EH_REGION, GEN_INT (rn)); } if (ecf_flags & ECF_NORETURN) - REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_NORETURN, const0_rtx, - REG_NOTES (call_insn)); + add_reg_note (call_insn, REG_NORETURN, const0_rtx); if (ecf_flags & ECF_RETURNS_TWICE) { - REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_SETJMP, const0_rtx, - REG_NOTES (call_insn)); + add_reg_note (call_insn, REG_SETJMP, const0_rtx); cfun->calls_setjmp = 1; } @@ -2814,8 +2810,7 @@ expand_call (tree exp, rtx target, int ignore) /* The return value from a malloc-like function can not alias anything else. */ last = get_last_insn (); - REG_NOTES (last) = - gen_rtx_EXPR_LIST (REG_NOALIAS, temp, REG_NOTES (last)); + add_reg_note (last, REG_NOALIAS, temp); /* Write out the sequence. */ insns = get_insns (); diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index afa3e123106..6a48e1632d7 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -67,18 +67,14 @@ add_reg_br_prob_note (rtx last, int probability) || NEXT_INSN (NEXT_INSN (NEXT_INSN (NEXT_INSN (last))))) goto failed; gcc_assert (!find_reg_note (last, REG_BR_PROB, 0)); - REG_NOTES (last) - = gen_rtx_EXPR_LIST (REG_BR_PROB, - GEN_INT (REG_BR_PROB_BASE - probability), - REG_NOTES (last)); + add_reg_note (last, REG_BR_PROB, + GEN_INT (REG_BR_PROB_BASE - probability)); return; } if (!last || !JUMP_P (last) || !any_condjump_p (last)) goto failed; gcc_assert (!find_reg_note (last, REG_BR_PROB, 0)); - REG_NOTES (last) - = gen_rtx_EXPR_LIST (REG_BR_PROB, - GEN_INT (probability), REG_NOTES (last)); + add_reg_note (last, REG_BR_PROB, GEN_INT (probability)); return; failed: if (dump_file) diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c index 623e5bdd911..e4049d66465 100644 --- a/gcc/cfglayout.c +++ b/gcc/cfglayout.c @@ -855,8 +855,7 @@ fixup_reorder_chain (void) && JUMP_P (BB_END (bb)) && !any_condjump_p (BB_END (bb)) && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING)) - REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST - (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb))); + add_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX); } } diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 8ce39006cf3..240455bca9d 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -1111,11 +1111,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target) && JUMP_P (BB_END (jump_block)) && !any_condjump_p (BB_END (jump_block)) && (EDGE_SUCC (jump_block, 0)->flags & EDGE_CROSSING)) - REG_NOTES (BB_END (jump_block)) = gen_rtx_EXPR_LIST (REG_CROSSING_JUMP, - NULL_RTX, - REG_NOTES - (BB_END - (jump_block))); + add_reg_note (BB_END (jump_block), REG_CROSSING_JUMP, NULL_RTX); /* Wire edge in. */ new_edge = make_edge (e->src, jump_block, EDGE_FALLTHRU); @@ -1418,8 +1414,7 @@ commit_one_edge_insertion (edge e) if (JUMP_P (BB_END (bb)) && !any_condjump_p (BB_END (bb)) && (single_succ_edge (bb)->flags & EDGE_CROSSING)) - REG_NOTES (BB_END (bb)) = gen_rtx_EXPR_LIST - (REG_CROSSING_JUMP, NULL_RTX, REG_NOTES (BB_END (bb))); + add_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX); } } } diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 17ee8f0a63a..6a80bbed095 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -109,6 +109,9 @@ int cgraph_n_nodes; /* Maximal uid used in cgraph nodes. */ int cgraph_max_uid; +/* Maximal uid used in cgraph edges. */ +int cgraph_edge_max_uid; + /* Maximal pid used for profiling */ int cgraph_max_pid; @@ -132,6 +135,206 @@ static GTY(()) struct cgraph_asm_node *cgraph_asm_last_node; them, to support -fno-toplevel-reorder. */ int cgraph_order; +/* List of hooks trigerred on cgraph_edge events. */ +struct cgraph_edge_hook_list { + cgraph_edge_hook hook; + void *data; + struct cgraph_edge_hook_list *next; +}; + +/* List of hooks trigerred on cgraph_node events. */ +struct cgraph_node_hook_list { + cgraph_node_hook hook; + void *data; + struct cgraph_node_hook_list *next; +}; + +/* List of hooks trigerred on events involving two cgraph_edges. */ +struct cgraph_2edge_hook_list { + cgraph_2edge_hook hook; + void *data; + struct cgraph_2edge_hook_list *next; +}; + +/* List of hooks trigerred on events involving two cgraph_nodes. */ +struct cgraph_2node_hook_list { + cgraph_2node_hook hook; + void *data; + struct cgraph_2node_hook_list *next; +}; + +/* List of hooks triggered when an edge is removed. */ +struct cgraph_edge_hook_list *first_cgraph_edge_removal_hook; +/* List of hooks triggered when a node is removed. */ +struct cgraph_node_hook_list *first_cgraph_node_removal_hook; +/* List of hooks triggered when an edge is duplicated. */ +struct cgraph_2edge_hook_list *first_cgraph_edge_duplicated_hook; +/* List of hooks triggered when a node is duplicated. */ +struct cgraph_2node_hook_list *first_cgraph_node_duplicated_hook; + + +/* Register HOOK to be called with DATA on each removed edge. */ +struct cgraph_edge_hook_list * +cgraph_add_edge_removal_hook (cgraph_edge_hook hook, void *data) +{ + struct cgraph_edge_hook_list *entry; + struct cgraph_edge_hook_list **ptr = &first_cgraph_edge_removal_hook; + + entry = (struct cgraph_edge_hook_list *) xmalloc (sizeof (*entry)); + entry->hook = hook; + entry->data = data; + entry->next = NULL; + while (*ptr) + ptr = &(*ptr)->next; + *ptr = entry; + return entry; +} + +/* Remove ENTRY from the list of hooks called on removing edges. */ +void +cgraph_remove_edge_removal_hook (struct cgraph_edge_hook_list *entry) +{ + struct cgraph_edge_hook_list **ptr = &first_cgraph_edge_removal_hook; + + while (*ptr != entry) + ptr = &(*ptr)->next; + *ptr = entry->next; +} + +/* Call all edge removal hooks. */ +static void +cgraph_call_edge_removal_hooks (struct cgraph_edge *e) +{ + struct cgraph_edge_hook_list *entry = first_cgraph_edge_removal_hook; + while (entry) + { + entry->hook (e, entry->data); + entry = entry->next; + } +} + +/* Register HOOK to be called with DATA on each removed node. */ +struct cgraph_node_hook_list * +cgraph_add_node_removal_hook (cgraph_node_hook hook, void *data) +{ + struct cgraph_node_hook_list *entry; + struct cgraph_node_hook_list **ptr = &first_cgraph_node_removal_hook; + + entry = (struct cgraph_node_hook_list *) xmalloc (sizeof (*entry)); + entry->hook = hook; + entry->data = data; + entry->next = NULL; + while (*ptr) + ptr = &(*ptr)->next; + *ptr = entry; + return entry; +} + +/* Remove ENTRY from the list of hooks called on removing nodes. */ +void +cgraph_remove_node_removal_hook (struct cgraph_node_hook_list *entry) +{ + struct cgraph_node_hook_list **ptr = &first_cgraph_node_removal_hook; + + while (*ptr != entry) + ptr = &(*ptr)->next; + *ptr = entry->next; +} + +/* Call all node removal hooks. */ +static void +cgraph_call_node_removal_hooks (struct cgraph_node *node) +{ + struct cgraph_node_hook_list *entry = first_cgraph_node_removal_hook; + while (entry) + { + entry->hook (node, entry->data); + entry = entry->next; + } +} + +/* Register HOOK to be called with DATA on each duplicated edge. */ +struct cgraph_2edge_hook_list * +cgraph_add_edge_duplication_hook (cgraph_2edge_hook hook, void *data) +{ + struct cgraph_2edge_hook_list *entry; + struct cgraph_2edge_hook_list **ptr = &first_cgraph_edge_duplicated_hook; + + entry = (struct cgraph_2edge_hook_list *) xmalloc (sizeof (*entry)); + entry->hook = hook; + entry->data = data; + entry->next = NULL; + while (*ptr) + ptr = &(*ptr)->next; + *ptr = entry; + return entry; +} + +/* Remove ENTRY from the list of hooks called on duplicating edges. */ +void +cgraph_remove_edge_duplication_hook (struct cgraph_2edge_hook_list *entry) +{ + struct cgraph_2edge_hook_list **ptr = &first_cgraph_edge_duplicated_hook; + + while (*ptr != entry) + ptr = &(*ptr)->next; + *ptr = entry->next; +} + +/* Call all edge duplication hooks. */ +static void +cgraph_call_edge_duplication_hooks (struct cgraph_edge *cs1, + struct cgraph_edge *cs2) +{ + struct cgraph_2edge_hook_list *entry = first_cgraph_edge_duplicated_hook; + while (entry) + { + entry->hook (cs1, cs2, entry->data); + entry = entry->next; + } +} + +/* Register HOOK to be called with DATA on each duplicated node. */ +struct cgraph_2node_hook_list * +cgraph_add_node_duplication_hook (cgraph_2node_hook hook, void *data) +{ + struct cgraph_2node_hook_list *entry; + struct cgraph_2node_hook_list **ptr = &first_cgraph_node_duplicated_hook; + + entry = (struct cgraph_2node_hook_list *) xmalloc (sizeof (*entry)); + entry->hook = hook; + entry->data = data; + entry->next = NULL; + while (*ptr) + ptr = &(*ptr)->next; + *ptr = entry; + return entry; +} + +/* Remove ENTRY from the list of hooks called on duplicating nodes. */ +void +cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *entry) +{ + struct cgraph_2node_hook_list **ptr = &first_cgraph_node_duplicated_hook; + + while (*ptr != entry) + ptr = &(*ptr)->next; + *ptr = entry->next; +} + +/* Call all node duplication hooks. */ +static void +cgraph_call_node_duplication_hooks (struct cgraph_node *node1, + struct cgraph_node *node2) +{ + struct cgraph_2node_hook_list *entry = first_cgraph_node_duplicated_hook; + while (entry) + { + entry->hook (node1, node2, entry->data); + entry = entry->next; + } +} + /* Returns a hash code for P. */ static hashval_t @@ -365,6 +568,7 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee, gcc_assert (freq >= 0); gcc_assert (freq <= CGRAPH_FREQ_MAX); edge->loop_nest = nest; + edge->uid = cgraph_edge_max_uid++; if (caller->call_site_hash) { void **slot; @@ -414,6 +618,7 @@ cgraph_edge_remove_caller (struct cgraph_edge *e) void cgraph_remove_edge (struct cgraph_edge *e) { + cgraph_call_edge_removal_hooks (e); /* Remove from callers list of the callee. */ cgraph_edge_remove_callee (e); @@ -495,7 +700,10 @@ cgraph_node_remove_callees (struct cgraph_node *node) the callees. The callee list of the node can be zapped with one assignment. */ for (e = node->callees; e; e = e->next_callee) - cgraph_edge_remove_callee (e); + { + cgraph_call_edge_removal_hooks (e); + cgraph_edge_remove_callee (e); + } node->callees = NULL; if (node->call_site_hash) { @@ -515,7 +723,10 @@ cgraph_node_remove_callers (struct cgraph_node *node) the callers. The caller list of the node can be zapped with one assignment. */ for (e = node->callers; e; e = e->next_caller) - cgraph_edge_remove_caller (e); + { + cgraph_call_edge_removal_hooks (e); + cgraph_edge_remove_caller (e); + } node->callers = NULL; } @@ -549,6 +760,7 @@ cgraph_remove_node (struct cgraph_node *node) void **slot; bool kill_body = false; + cgraph_call_node_removal_hooks (node); cgraph_node_remove_callers (node); cgraph_node_remove_callees (node); /* Incremental inlining access removed nodes stored in the postorder list. @@ -891,6 +1103,7 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n, if (e->count < 0) e->count = 0; } + cgraph_call_edge_duplication_hooks (e, new); return new; } @@ -942,6 +1155,7 @@ cgraph_clone_node (struct cgraph_node *n, gcov_type count, int freq, int loop_ne if (new->next_clone) new->next_clone->prev_clone = new; + cgraph_call_node_duplication_hooks (n, new); return new; } diff --git a/gcc/cgraph.h b/gcc/cgraph.h index dda2a1891f5..ee79c9200f1 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -209,6 +209,8 @@ struct cgraph_edge GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_call int frequency; /* Depth of loop nest, 1 means no loop nest. */ int loop_nest; + /* Unique id of the edge. */ + int uid; }; #define CGRAPH_FREQ_BASE 1000 @@ -266,6 +268,7 @@ struct cgraph_asm_node GTY(()) extern GTY(()) struct cgraph_node *cgraph_nodes; extern GTY(()) int cgraph_n_nodes; extern GTY(()) int cgraph_max_uid; +extern GTY(()) int cgraph_edge_max_uid; extern GTY(()) int cgraph_max_pid; extern bool cgraph_global_info_ready; enum cgraph_state @@ -351,6 +354,26 @@ struct cgraph_node *save_inline_function_body (struct cgraph_node *); void record_references_in_initializer (tree); bool cgraph_process_new_functions (void); +typedef void (*cgraph_edge_hook)(struct cgraph_edge *, void *); +typedef void (*cgraph_node_hook)(struct cgraph_node *, void *); +typedef void (*cgraph_2edge_hook)(struct cgraph_edge *, struct cgraph_edge *, + void *); +typedef void (*cgraph_2node_hook)(struct cgraph_node *, struct cgraph_node *, + void *); +struct cgraph_edge_hook_list; +struct cgraph_node_hook_list; +struct cgraph_2edge_hook_list; +struct cgraph_2node_hook_list; +struct cgraph_edge_hook_list *cgraph_add_edge_removal_hook (cgraph_edge_hook, void *); +void cgraph_remove_edge_removal_hook (struct cgraph_edge_hook_list *); +struct cgraph_node_hook_list *cgraph_add_node_removal_hook (cgraph_node_hook, + void *); +void cgraph_remove_node_removal_hook (struct cgraph_node_hook_list *); +struct cgraph_2edge_hook_list *cgraph_add_edge_duplication_hook (cgraph_2edge_hook, void *); +void cgraph_remove_edge_duplication_hook (struct cgraph_2edge_hook_list *); +struct cgraph_2node_hook_list *cgraph_add_node_duplication_hook (cgraph_2node_hook, void *); +void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *); + /* In cgraphbuild.c */ unsigned int rebuild_cgraph_edges (void); diff --git a/gcc/combine.c b/gcc/combine.c index 59586a8bf18..a6cff36480f 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -12149,10 +12149,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx to_insn, for (i = deadregno; i < deadend; i++) if (i < regno || i >= ourend) - REG_NOTES (where_dead) - = gen_rtx_EXPR_LIST (REG_DEAD, - regno_reg_rtx[i], - REG_NOTES (where_dead)); + add_reg_note (where_dead, REG_DEAD, regno_reg_rtx[i]); } /* If we didn't find any note, or if we found a REG_DEAD note that @@ -12774,9 +12771,7 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2, || reg_bitfield_target_p (piece, PATTERN (tem))) { - REG_NOTES (tem) - = gen_rtx_EXPR_LIST (REG_UNUSED, piece, - REG_NOTES (tem)); + add_reg_note (tem, REG_UNUSED, piece); break; } } diff --git a/gcc/config.gcc b/gcc/config.gcc index f4f171e0c02..e73223b9b32 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -281,14 +281,14 @@ i[34567]86-*-*) extra_headers="cpuid.h mmintrin.h mm3dnow.h xmmintrin.h emmintrin.h pmmintrin.h tmmintrin.h ammintrin.h smmintrin.h nmmintrin.h bmmintrin.h mmintrin-common.h - wmmintrin.h" + wmmintrin.h cross-stdarg.h" ;; x86_64-*-*) cpu_type=i386 extra_headers="cpuid.h mmintrin.h mm3dnow.h xmmintrin.h emmintrin.h pmmintrin.h tmmintrin.h ammintrin.h smmintrin.h nmmintrin.h bmmintrin.h mmintrin-common.h - wmmintrin.h" + wmmintrin.h cross-stdarg.h" need_64bit_hwint=yes ;; ia64-*-*) @@ -1006,11 +1006,11 @@ i[34567]86-*-darwin*) # then this file using that to set --with-cpu=i386 which has no -m64 # support. with_cpu=${with_cpu:-generic} - tmake_file="${tmake_file} i386/t-fprules-softfp64 soft-fp/t-softfp i386/t-crtpc i386/t-crtfm" + tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm" ;; x86_64-*-darwin*) with_cpu=${with_cpu:-generic} - tmake_file="t-darwin ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-fprules-softfp64 soft-fp/t-softfp i386/t-crtpc i386/t-crtfm" + tmake_file="t-darwin ${cpu_type}/t-darwin64 t-slibgcc-darwin i386/t-crtpc i386/t-crtfm" tm_file="${tm_file} ${cpu_type}/darwin64.h" ;; i[34567]86-*-elf*) @@ -1069,7 +1069,7 @@ i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu) if test x$enable_targets = xall; then tm_file="${tm_file} i386/x86-64.h i386/linux64.h" tm_defines="${tm_defines} TARGET_BI_ARCH=1" - tmake_file="${tmake_file} i386/t-linux64 i386/t-fprules-softfp64 soft-fp/t-softfp" + tmake_file="${tmake_file} i386/t-linux64" need_64bit_hwint=yes case X"${with_cpu}" in Xgeneric|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx) @@ -1101,7 +1101,7 @@ x86_64-*-linux* | x86_64-*-kfreebsd*-gnu | x86_64-*-knetbsd*-gnu) x86_64-*-kfreebsd*-gnu) tm_file="${tm_file} kfreebsd-gnu.h" ;; x86_64-*-knetbsd*-gnu) tm_file="${tm_file} knetbsd-gnu.h" ;; esac - tmake_file="${tmake_file} i386/t-linux64 i386/t-crtstuff i386/t-crtpc i386/t-crtfm i386/t-fprules-softfp64 soft-fp/t-softfp t-dfprules" + tmake_file="${tmake_file} i386/t-linux64 i386/t-crtstuff i386/t-crtpc i386/t-crtfm t-dfprules" ;; i[34567]86-*-gnu*) ;; @@ -1459,9 +1459,11 @@ m68k-*-linux*) # Motorola m68k's running GNU/Linux # aka the GNU/Linux C library 6. default_m68k_cpu=68020 default_cf_cpu=5475 - tm_file="${tm_file} dbxelf.h elfos.h svr4.h linux.h m68k/linux.h" + with_arch=${with_arch:-m68k} + tm_file="${tm_file} dbxelf.h elfos.h svr4.h linux.h m68k/linux.h ./sysroot-suffix.h" extra_options="${extra_options} m68k/ieee.opt" tm_defines="${tm_defines} MOTOROLA=1" + tmake_file="${tmake_file} m68k/t-floatlib m68k/t-linux m68k/t-mlibs" # if not configured with --enable-sjlj-exceptions, bump the # libgcc version number if test x$sjlj != x1; then @@ -2973,6 +2975,13 @@ case ${target} in fi ;; + i[34567]86-*-darwin* | x86_64-*-darwin*) + tmake_file="${tmake_file} i386/t-fprules-softfp soft-fp/t-softfp" + ;; + i[34567]86-*-linux* | x86_64-*-linux*) + tmake_file="${tmake_file} i386/t-fprules-softfp soft-fp/t-softfp i386/t-linux" + ;; + mips*-*-*) if test x$gnu_ld = xyes then diff --git a/gcc/config.in b/gcc/config.in index 5e584c11fd7..5cf01cc04d3 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -192,12 +192,6 @@ #endif -/* Define to 1 if you have the `alphasort' function. */ -#ifndef USED_FOR_TARGET -#undef HAVE_ALPHASORT -#endif - - /* Define if your assembler supports cmpb. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_CMPB @@ -1152,12 +1146,6 @@ #endif -/* Define to 1 if you have the `scandir' function. */ -#ifndef USED_FOR_TARGET -#undef HAVE_SCANDIR -#endif - - /* Define to 1 if you have the `setlocale' function. */ #ifndef USED_FOR_TARGET #undef HAVE_SETLOCALE @@ -1548,6 +1536,12 @@ #endif +/* Define to `char *' if <sys/types.h> does not define. */ +#ifndef USED_FOR_TARGET +#undef caddr_t +#endif + + /* Define to `int' if <sys/types.h> doesn't define. */ #ifndef USED_FOR_TARGET #undef gid_t diff --git a/gcc/config/alpha/vms_tramp.asm b/gcc/config/alpha/vms_tramp.asm index d197521a887..66ab2f0de59 100644 --- a/gcc/config/alpha/vms_tramp.asm +++ b/gcc/config/alpha/vms_tramp.asm @@ -33,7 +33,6 @@ Boston, MA 02110-1301, USA. */ .set noreorder .set volatile .set noat - .file 1 "vms_tramp.asm" .text .align 3 .globl __tramp diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h index cb46a8edc90..59c1bf70e5d 100644 --- a/gcc/config/arm/aout.h +++ b/gcc/config/arm/aout.h @@ -191,9 +191,6 @@ } #endif -/* Arm Assembler barfs on dollars. */ -#define DOLLARS_IN_IDENTIFIERS 0 - #ifndef NO_DOLLAR_IN_LABEL #define NO_DOLLAR_IN_LABEL 1 #endif diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index fa3d06dcd75..0ce531bb802 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -15094,6 +15094,24 @@ arm_init_neon_builtins (void) TYPE_PRECISION (neon_float_type_node) = FLOAT_TYPE_SIZE; layout_type (neon_float_type_node); + /* Define typedefs which exactly correspond to the modes we are basing vector + types on. If you change these names you'll need to change + the table used by arm_mangle_type too. */ + (*lang_hooks.types.register_builtin_type) (neon_intQI_type_node, + "__builtin_neon_qi"); + (*lang_hooks.types.register_builtin_type) (neon_intHI_type_node, + "__builtin_neon_hi"); + (*lang_hooks.types.register_builtin_type) (neon_intSI_type_node, + "__builtin_neon_si"); + (*lang_hooks.types.register_builtin_type) (neon_float_type_node, + "__builtin_neon_sf"); + (*lang_hooks.types.register_builtin_type) (neon_intDI_type_node, + "__builtin_neon_di"); + (*lang_hooks.types.register_builtin_type) (neon_polyQI_type_node, + "__builtin_neon_poly8"); + (*lang_hooks.types.register_builtin_type) (neon_polyHI_type_node, + "__builtin_neon_poly16"); + intQI_pointer_node = build_pointer_type (neon_intQI_type_node); intHI_pointer_node = build_pointer_type (neon_intHI_type_node); intSI_pointer_node = build_pointer_type (neon_intSI_type_node); @@ -15146,12 +15164,32 @@ arm_init_neon_builtins (void) intUSI_type_node = make_unsigned_type (GET_MODE_PRECISION (SImode)); intUDI_type_node = make_unsigned_type (GET_MODE_PRECISION (DImode)); + (*lang_hooks.types.register_builtin_type) (intUQI_type_node, + "__builtin_neon_uqi"); + (*lang_hooks.types.register_builtin_type) (intUHI_type_node, + "__builtin_neon_uhi"); + (*lang_hooks.types.register_builtin_type) (intUSI_type_node, + "__builtin_neon_usi"); + (*lang_hooks.types.register_builtin_type) (intUDI_type_node, + "__builtin_neon_udi"); + /* Opaque integer types for structures of vectors. */ intEI_type_node = make_signed_type (GET_MODE_PRECISION (EImode)); intOI_type_node = make_signed_type (GET_MODE_PRECISION (OImode)); intCI_type_node = make_signed_type (GET_MODE_PRECISION (CImode)); intXI_type_node = make_signed_type (GET_MODE_PRECISION (XImode)); + (*lang_hooks.types.register_builtin_type) (intTI_type_node, + "__builtin_neon_ti"); + (*lang_hooks.types.register_builtin_type) (intEI_type_node, + "__builtin_neon_ei"); + (*lang_hooks.types.register_builtin_type) (intOI_type_node, + "__builtin_neon_oi"); + (*lang_hooks.types.register_builtin_type) (intCI_type_node, + "__builtin_neon_ci"); + (*lang_hooks.types.register_builtin_type) (intXI_type_node, + "__builtin_neon_xi"); + /* Pointers to vector types. */ V8QI_pointer_node = build_pointer_type (V8QI_type_node); V4HI_pointer_node = build_pointer_type (V4HI_type_node); @@ -15195,44 +15233,6 @@ arm_init_neon_builtins (void) build_function_type_list (void_type_node, V2DI_pointer_node, V2DI_type_node, V2DI_type_node, NULL); - /* Define typedefs which exactly correspond to the modes we are basing vector - types on. If you change these names you'll need to change - the table used by arm_mangle_type too. */ - (*lang_hooks.types.register_builtin_type) (neon_intQI_type_node, - "__builtin_neon_qi"); - (*lang_hooks.types.register_builtin_type) (neon_intHI_type_node, - "__builtin_neon_hi"); - (*lang_hooks.types.register_builtin_type) (neon_intSI_type_node, - "__builtin_neon_si"); - (*lang_hooks.types.register_builtin_type) (neon_float_type_node, - "__builtin_neon_sf"); - (*lang_hooks.types.register_builtin_type) (neon_intDI_type_node, - "__builtin_neon_di"); - - (*lang_hooks.types.register_builtin_type) (neon_polyQI_type_node, - "__builtin_neon_poly8"); - (*lang_hooks.types.register_builtin_type) (neon_polyHI_type_node, - "__builtin_neon_poly16"); - (*lang_hooks.types.register_builtin_type) (intUQI_type_node, - "__builtin_neon_uqi"); - (*lang_hooks.types.register_builtin_type) (intUHI_type_node, - "__builtin_neon_uhi"); - (*lang_hooks.types.register_builtin_type) (intUSI_type_node, - "__builtin_neon_usi"); - (*lang_hooks.types.register_builtin_type) (intUDI_type_node, - "__builtin_neon_udi"); - - (*lang_hooks.types.register_builtin_type) (intTI_type_node, - "__builtin_neon_ti"); - (*lang_hooks.types.register_builtin_type) (intEI_type_node, - "__builtin_neon_ei"); - (*lang_hooks.types.register_builtin_type) (intOI_type_node, - "__builtin_neon_oi"); - (*lang_hooks.types.register_builtin_type) (intCI_type_node, - "__builtin_neon_ci"); - (*lang_hooks.types.register_builtin_type) (intXI_type_node, - "__builtin_neon_xi"); - dreg_types[0] = V8QI_type_node; dreg_types[1] = V4HI_type_node; dreg_types[2] = V2SI_type_node; diff --git a/gcc/config/arm/crti.asm b/gcc/config/arm/crti.asm index 6f0acd199e0..c77651a5191 100644 --- a/gcc/config/arm/crti.asm +++ b/gcc/config/arm/crti.asm @@ -64,8 +64,6 @@ #endif .endm - .file "crti.asm" - .section ".init" .align 2 .global _init diff --git a/gcc/config/arm/crtn.asm b/gcc/config/arm/crtn.asm index 36c417d7dde..34b95d943d9 100644 --- a/gcc/config/arm/crtn.asm +++ b/gcc/config/arm/crtn.asm @@ -72,8 +72,6 @@ .endm - .file "crtn.asm" - .section ".init" ;; FUNC_END diff --git a/gcc/config/bfin/crti.s b/gcc/config/bfin/crti.s index c9753599986..8ddedcbfd18 100644 --- a/gcc/config/bfin/crti.s +++ b/gcc/config/bfin/crti.s @@ -31,7 +31,6 @@ Boston, MA 02110-1301, USA. */ * sections. It is linked in before crtbegin.o. */ - .file "crti.o" .ident "GNU C crti.o" .section .init diff --git a/gcc/config/bfin/crtlibid.s b/gcc/config/bfin/crtlibid.s index f80adfe7ec9..d4f7ee5e693 100644 --- a/gcc/config/bfin/crtlibid.s +++ b/gcc/config/bfin/crtlibid.s @@ -25,7 +25,6 @@ Boston, MA 02110-1301, USA. */ This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. */ - .file "crtlibid.o" .ident "GNU C crtlibid.o" .weak _current_shared_library_p5_offset_ diff --git a/gcc/config/bfin/crtn.s b/gcc/config/bfin/crtn.s index 06af2bea9e7..aff49b7984a 100644 --- a/gcc/config/bfin/crtn.s +++ b/gcc/config/bfin/crtn.s @@ -31,7 +31,6 @@ Boston, MA 02110-1301, USA. */ * It is linked in after all other files. */ - .file "crtn.o" .ident "GNU C crtn.o" .section .init diff --git a/gcc/config/fr30/crti.asm b/gcc/config/fr30/crti.asm index cd2bd82c0c3..acc8e07e7c4 100644 --- a/gcc/config/fr30/crti.asm +++ b/gcc/config/fr30/crti.asm @@ -37,8 +37,6 @@ # .init sections. Users may put any desired instructions in those # sections. - .file "crti.asm" - .section ".init" .global _init .type _init,#function diff --git a/gcc/config/fr30/crtn.asm b/gcc/config/fr30/crtn.asm index ad175b2eb75..e1b308f4da7 100644 --- a/gcc/config/fr30/crtn.asm +++ b/gcc/config/fr30/crtn.asm @@ -37,8 +37,6 @@ # fact return. Users may put any desired instructions in those sections. # This file is the last thing linked into any executable. - .file "crtn.s" - .section ".init" .align 4 diff --git a/gcc/config/frv/lib1funcs.asm b/gcc/config/frv/lib1funcs.asm index af02459d2aa..ddd3fe9d5ef 100644 --- a/gcc/config/frv/lib1funcs.asm +++ b/gcc/config/frv/lib1funcs.asm @@ -32,7 +32,6 @@ #ifdef L_cmpll /* icc0 = __cmpll (long long a, long long b) */ - .file "_cmpll.s" .globl EXT(__cmpll) .type EXT(__cmpll),@function .text @@ -51,7 +50,6 @@ EXT(__cmpll): /* Note, because this function returns the result in ICC0, it means it can't handle NaNs. */ - .file "_cmpf.s" .globl EXT(__cmpf) .type EXT(__cmpf),@function .text @@ -91,7 +89,6 @@ EXT(__cmpf): /* Note, because this function returns the result in ICC0, it means it can't handle NaNs. */ - .file "_cmpd.s" .globl EXT(__cmpd) .type EXT(__cmpd),@function .text @@ -118,7 +115,6 @@ EXT(__cmpd): /* Note, gcc will never call this function, but it is present in case an ABI program calls it. */ - .file "_addll.s" .globl EXT(__addll) .type EXT(__addll),@function .text @@ -136,7 +132,6 @@ EXT(__addll): /* Note, gcc will never call this function, but it is present in case an ABI program calls it. */ - .file "_subll.s" .globl EXT(__subll) .type EXT(__subll),@function .text @@ -154,7 +149,6 @@ EXT(__subll): /* Note, gcc will never call this function, but it is present in case an ABI program calls it. */ - .file "_andll.s" .globl EXT(__andll) .type EXT(__andll),@function .text @@ -172,7 +166,6 @@ EXT(__andll): /* Note, gcc will never call this function, but it is present in case an ABI program calls it. */ - .file "_orll.s" .globl EXT(__orll) .type EXT(__orll),@function .text @@ -190,7 +183,6 @@ EXT(__orll): /* Note, gcc will never call this function, but it is present in case an ABI program calls it. */ - .file "_xorll.s" .globl EXT(__xorll) .type EXT(__xorll),@function .text @@ -208,7 +200,6 @@ EXT(__xorll): /* Note, gcc will never call this function, but it is present in case an ABI program calls it. */ - .file "_notll.s" .globl EXT(__notll) .type EXT(__notll),@function .text @@ -241,7 +232,6 @@ EXT(__notll): * } */ - .file "_cmov.s" .globl EXT(__cmov) .type EXT(__cmov),@function .text diff --git a/gcc/config/host-solaris.c b/gcc/config/host-solaris.c index 9a471b49f4c..bde01db9813 100644 --- a/gcc/config/host-solaris.c +++ b/gcc/config/host-solaris.c @@ -42,7 +42,7 @@ sol_gt_pch_use_address (void *base, size_t size, int fd, size_t offset) if (size == 0) return -1; - addr = mmap (base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, + addr = mmap ((caddr_t) base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); /* Solaris isn't good about honoring the mmap START parameter @@ -55,18 +55,18 @@ sol_gt_pch_use_address (void *base, size_t size, int fd, size_t offset) size_t i; if (addr != (void *) MAP_FAILED) - munmap (addr, size); + munmap ((caddr_t) addr, size); errno = 0; for (i = 0; i < size; i += page_size) - if (mincore ((char *)base + i, page_size, (void *)&one_byte) == -1 + if (mincore ((char *)base + i, page_size, (char *) &one_byte) == -1 && errno == ENOMEM) continue; /* The page is not mapped. */ else break; if (i >= size) - addr = mmap (base, size, + addr = mmap ((caddr_t) base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, offset); } diff --git a/gcc/config/i386/cross-stdarg.h b/gcc/config/i386/cross-stdarg.h new file mode 100644 index 00000000000..98ac1ecd5cc --- /dev/null +++ b/gcc/config/i386/cross-stdarg.h @@ -0,0 +1,76 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Free Software Foundation, Inc. + + 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, 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, if you include this header file into source + files compiled by GCC, this header file does not by itself cause + the resulting executable to be covered by the GNU General Public + License. This exception does not however invalidate any other + reasons why the executable file might be covered by the GNU General + Public License. */ + +#ifndef __CROSS_STDARG_H_INCLUDED +#define __CROSS_STDARG_H_INCLUDED + +/* Make sure that for non x64 targets cross builtins are defined. */ +#ifndef __x86_64__ +/* Call abi ms_abi. */ +#define __builtin_ms_va_list __builtin_va_list +#define __builtin_ms_va_copy __builtin_va_copy +#define __builtin_ms_va_start __builtin_va_start +#define __builtin_ms_va_end __builtin_va_end + +/* Call abi sysv_abi. */ +#define __builtin_sysv_va_list __builtin_va_list +#define __builtin_sysv_va_copy __builtin_va_copy +#define __builtin_sysv_va_start __builtin_va_start +#define __builtin_sysv_va_end __builtin_va_end +#endif + +#define __ms_va_copy(__d,__s) __builtin_ms_va_copy(__d,__s) +#define __ms_va_start(__v,__l) __builtin_ms_va_start(__v,__l) +#define __ms_va_arg(__v,__l) __builtin_va_arg(__v,__l) +#define __ms_va_end(__v) __builtin_ms_va_end(__v) + +#define __sysv_va_copy(__d,__s) __builtin_sysv_va_copy(__d,__s) +#define __sysv_va_start(__v,__l) __builtin_sysv_va_start(__v,__l) +#define __sysv_va_arg(__v,__l) __builtin_va_arg(__v,__l) +#define __sysv_va_end(__v) __builtin_sysv_va_end(__v) + +#ifndef __GNUC_SYSV_VA_LIST +#define __GNUC_SYSV_VA_LIST + typedef __builtin_sysv_va_list __gnuc_sysv_va_list; +#endif + +#ifndef _SYSV_VA_LIST_DEFINED +#define _SYSV_VA_LIST_DEFINED + typedef __gnuc_sysv_va_list sysv_va_list; +#endif + +#ifndef __GNUC_MS_VA_LIST +#define __GNUC_MS_VA_LIST + typedef __builtin_ms_va_list __gnuc_ms_va_list; +#endif + +#ifndef _MS_VA_LIST_DEFINED +#define _MS_VA_LIST_DEFINED + typedef __gnuc_ms_va_list ms_va_list; +#endif + +#endif /* __CROSS_STDARG_H_INCLUDED */ diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 8d0772dbe8b..9719ec2886f 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -141,6 +141,9 @@ extern int ix86_cfun_abi (void); extern int ix86_function_abi (const_tree); extern int ix86_function_type_abi (const_tree); extern void ix86_call_abi_override (const_tree); +extern tree ix86_fn_abi_va_list (tree); +extern tree ix86_canonical_va_list_type (tree); +extern int ix86_enum_va_list (int, const char **, tree *); extern int ix86_reg_parm_stack_space (const_tree); extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx, diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 5a2c0c870a7..26999e71d5b 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1716,6 +1716,10 @@ unsigned int ix86_preferred_stack_boundary; /* Values 1-5: see jump.c */ int ix86_branch_cost; +/* Calling abi specific va_list type nodes. */ +static GTY(()) tree sysv_va_list_type_node; +static GTY(()) tree ms_va_list_type_node; + /* Variables which are this size or smaller are put in the data/bss or ldata/lbss sections. */ @@ -2774,9 +2778,8 @@ override_options (void) set_param_value ("l2-cache-size", ix86_cost->l2_cache_size); /* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0) - can be optimized to ap = __builtin_next_arg (0). - For abi switching it should be corrected. */ - if (!TARGET_64BIT || DEFAULT_ABI == MS_ABI) + can be optimized to ap = __builtin_next_arg (0). */ + if (!TARGET_64BIT) targetm.expand_builtin_va_start = NULL; if (TARGET_64BIT) @@ -3201,7 +3204,7 @@ ix86_handle_cconv_attribute (tree *node, tree name, if (TARGET_64BIT) { /* Do not warn when emulating the MS ABI. */ - if (TREE_CODE (*node) != FUNCTION_TYPE || !ix86_function_type_abi (*node)) + if (TREE_CODE (*node) != FUNCTION_TYPE || ix86_function_type_abi (*node)!=MS_ABI) warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name)); *no_add_attrs = true; @@ -3604,9 +3607,6 @@ ix86_function_type_abi (const_tree fntype) else abi = lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (fntype)) ? SYSV_ABI : MS_ABI; - if (DEFAULT_ABI == MS_ABI && abi == SYSV_ABI) - sorry ("using sysv calling convention on target w64 is not supported"); - return abi; } return DEFAULT_ABI; @@ -4746,7 +4746,8 @@ contains_aligned_value_p (tree type) enum machine_mode mode = TYPE_MODE (type); if (((TARGET_SSE && SSE_REG_MODE_P (mode)) || mode == TDmode - || mode == TFmode) + || mode == TFmode + || mode == TCmode) && (!TYPE_USER_ALIGN (type) || TYPE_ALIGN (type) > 128)) return true; if (TYPE_ALIGN (type) < 128) @@ -5173,13 +5174,16 @@ ix86_struct_value_rtx (tree type, int incoming ATTRIBUTE_UNUSED) /* Create the va_list data type. */ +/* Returns the calling convention specific va_list date type. + The argument ABI can be DEFAULT_ABI, MS_ABI, or SYSV_ABI. */ + static tree -ix86_build_builtin_va_list (void) +ix86_build_builtin_va_list_abi (enum calling_abi abi) { tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl; /* For i386 we use plain pointer to argument area. */ - if (!TARGET_64BIT || ix86_cfun_abi () == MS_ABI) + if (!TARGET_64BIT || abi == MS_ABI) return build_pointer_type (char_type_node); record = (*lang_hooks.types.make_type) (RECORD_TYPE); @@ -5215,6 +5219,51 @@ ix86_build_builtin_va_list (void) return build_array_type (record, build_index_type (size_zero_node)); } +/* Setup the builtin va_list data type and for 64-bit the additional + calling convention specific va_list data types. */ + +static tree +ix86_build_builtin_va_list (void) +{ + tree ret = ix86_build_builtin_va_list_abi (DEFAULT_ABI); + + /* Initialize abi specific va_list builtin types. */ + if (TARGET_64BIT) + { + tree t; + if (DEFAULT_ABI == MS_ABI) + { + t = ix86_build_builtin_va_list_abi (SYSV_ABI); + if (TREE_CODE (t) != RECORD_TYPE) + t = build_variant_type_copy (t); + sysv_va_list_type_node = t; + } + else + { + t = ret; + if (TREE_CODE (t) != RECORD_TYPE) + t = build_variant_type_copy (t); + sysv_va_list_type_node = t; + } + if (DEFAULT_ABI != MS_ABI) + { + t = ix86_build_builtin_va_list_abi (MS_ABI); + if (TREE_CODE (t) != RECORD_TYPE) + t = build_variant_type_copy (t); + ms_va_list_type_node = t; + } + else + { + t = ret; + if (TREE_CODE (t) != RECORD_TYPE) + t = build_variant_type_copy (t); + ms_va_list_type_node = t; + } + } + + return ret; +} + /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */ static void @@ -5359,6 +5408,21 @@ ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, setup_incoming_varargs_64 (&next_cum); } +/* Checks if TYPE is of kind va_list char *. */ + +static bool +is_va_list_char_pointer (tree type) +{ + tree canonic; + + /* For 32-bit it is always true. */ + if (!TARGET_64BIT) + return true; + canonic = ix86_canonical_va_list_type (type); + return (canonic == ms_va_list_type_node + || (DEFAULT_ABI == MS_ABI && canonic == va_list_type_node)); +} + /* Implement va_start. */ static void @@ -5370,13 +5434,13 @@ ix86_va_start (tree valist, rtx nextarg) tree type; /* Only 64bit target needs something special. */ - if (!TARGET_64BIT || cfun->machine->call_abi == MS_ABI) + if (!TARGET_64BIT || is_va_list_char_pointer (TREE_TYPE (valist))) { std_expand_builtin_va_start (valist, nextarg); return; } - f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); + f_gpr = TYPE_FIELDS (TREE_TYPE (sysv_va_list_type_node)); f_fpr = TREE_CHAIN (f_gpr); f_ovf = TREE_CHAIN (f_fpr); f_sav = TREE_CHAIN (f_ovf); @@ -5449,10 +5513,10 @@ ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) enum machine_mode nat_mode; /* Only 64bit target needs something special. */ - if (!TARGET_64BIT || cfun->machine->call_abi == MS_ABI) + if (!TARGET_64BIT || is_va_list_char_pointer (TREE_TYPE (valist))) return std_gimplify_va_arg_expr (valist, type, pre_p, post_p); - f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); + f_gpr = TYPE_FIELDS (TREE_TYPE (sysv_va_list_type_node)); f_fpr = TREE_CHAIN (f_gpr); f_ovf = TREE_CHAIN (f_fpr); f_sav = TREE_CHAIN (f_ovf); @@ -17103,7 +17167,8 @@ ix86_data_alignment (tree type, int align) if (TYPE_MODE (type) == DCmode && align < 64) return 64; - if (TYPE_MODE (type) == XCmode && align < 128) + if ((TYPE_MODE (type) == XCmode + || TYPE_MODE (type) == TCmode) && align < 128) return 128; } else if ((TREE_CODE (type) == RECORD_TYPE @@ -17169,7 +17234,8 @@ ix86_local_alignment (tree type, enum machine_mode mode, { if (TYPE_MODE (type) == DCmode && align < 64) return 64; - if (TYPE_MODE (type) == XCmode && align < 128) + if ((TYPE_MODE (type) == XCmode + || TYPE_MODE (type) == TCmode) && align < 128) return 128; } else if ((TREE_CODE (type) == RECORD_TYPE @@ -20213,6 +20279,55 @@ ix86_init_mmx_sse_builtins (void) } } +/* Internal method for ix86_init_builtins. */ + +static void +ix86_init_builtins_va_builtins_abi (void) +{ + tree ms_va_ref, sysv_va_ref; + tree fnvoid_va_end_ms, fnvoid_va_end_sysv; + tree fnvoid_va_start_ms, fnvoid_va_start_sysv; + tree fnvoid_va_copy_ms, fnvoid_va_copy_sysv; + tree fnattr_ms = NULL_TREE, fnattr_sysv = NULL_TREE; + + if (!TARGET_64BIT) + return; + fnattr_ms = build_tree_list (get_identifier ("ms_abi"), NULL_TREE); + fnattr_sysv = build_tree_list (get_identifier ("sysv_abi"), NULL_TREE); + ms_va_ref = build_reference_type (ms_va_list_type_node); + sysv_va_ref = + build_pointer_type (TREE_TYPE (sysv_va_list_type_node)); + + fnvoid_va_end_ms = + build_function_type_list (void_type_node, ms_va_ref, NULL_TREE); + fnvoid_va_start_ms = + build_varargs_function_type_list (void_type_node, ms_va_ref, NULL_TREE); + fnvoid_va_end_sysv = + build_function_type_list (void_type_node, sysv_va_ref, NULL_TREE); + fnvoid_va_start_sysv = + build_varargs_function_type_list (void_type_node, sysv_va_ref, + NULL_TREE); + fnvoid_va_copy_ms = + build_function_type_list (void_type_node, ms_va_ref, ms_va_list_type_node, + NULL_TREE); + fnvoid_va_copy_sysv = + build_function_type_list (void_type_node, sysv_va_ref, + sysv_va_ref, NULL_TREE); + + add_builtin_function ("__builtin_ms_va_start", fnvoid_va_start_ms, + BUILT_IN_VA_START, BUILT_IN_NORMAL, NULL, fnattr_ms); + add_builtin_function ("__builtin_ms_va_end", fnvoid_va_end_ms, + BUILT_IN_VA_END, BUILT_IN_NORMAL, NULL, fnattr_ms); + add_builtin_function ("__builtin_ms_va_copy", fnvoid_va_copy_ms, + BUILT_IN_VA_COPY, BUILT_IN_NORMAL, NULL, fnattr_ms); + add_builtin_function ("__builtin_sysv_va_start", fnvoid_va_start_sysv, + BUILT_IN_VA_START, BUILT_IN_NORMAL, NULL, fnattr_sysv); + add_builtin_function ("__builtin_sysv_va_end", fnvoid_va_end_sysv, + BUILT_IN_VA_END, BUILT_IN_NORMAL, NULL, fnattr_sysv); + add_builtin_function ("__builtin_sysv_va_copy", fnvoid_va_copy_sysv, + BUILT_IN_VA_COPY, BUILT_IN_NORMAL, NULL, fnattr_sysv); +} + static void ix86_init_builtins (void) { @@ -20247,19 +20362,31 @@ ix86_init_builtins (void) NULL, NULL_TREE); ix86_builtins[(int) IX86_BUILTIN_INFQ] = decl; + /* We will expand them to normal call if SSE2 isn't available since + they are used by libgcc. */ ftype = build_function_type_list (float128_type_node, float128_type_node, NULL_TREE); - def_builtin_const (OPTION_MASK_ISA_SSE2, "__builtin_fabsq", ftype, IX86_BUILTIN_FABSQ); + decl = add_builtin_function ("__builtin_fabsq", ftype, + IX86_BUILTIN_FABSQ, BUILT_IN_MD, + "__fabstf2", NULL_TREE); + ix86_builtins[(int) IX86_BUILTIN_FABSQ] = decl; + TREE_READONLY (decl) = 1; ftype = build_function_type_list (float128_type_node, float128_type_node, float128_type_node, NULL_TREE); - def_builtin_const (OPTION_MASK_ISA_SSE2, "__builtin_copysignq", ftype, IX86_BUILTIN_COPYSIGNQ); + decl = add_builtin_function ("__builtin_copysignq", ftype, + IX86_BUILTIN_COPYSIGNQ, BUILT_IN_MD, + "__copysigntf3", NULL_TREE); + ix86_builtins[(int) IX86_BUILTIN_COPYSIGNQ] = decl; + TREE_READONLY (decl) = 1; if (TARGET_MMX) ix86_init_mmx_sse_builtins (); + if (TARGET_64BIT) + ix86_init_builtins_va_builtins_abi (); } /* Errors in the source file can cause expand_expr to return const0_rtx @@ -21610,7 +21737,16 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, i < ARRAY_SIZE (bdesc_args); i++, d++) if (d->code == fcode) - return ix86_expand_args_builtin (d, exp, target); + switch (fcode) + { + case IX86_BUILTIN_FABSQ: + case IX86_BUILTIN_COPYSIGNQ: + if (!TARGET_SSE2) + /* Emit a normal call if SSE2 isn't available. */ + return expand_call (exp, target, ignore); + default: + return ix86_expand_args_builtin (d, exp, target); + } for (i = 0, d = bdesc_comi; i < ARRAY_SIZE (bdesc_comi); i++, d++) if (d->code == fcode) @@ -23075,6 +23211,54 @@ x86_order_regs_for_local_alloc (void) reg_alloc_order [pos++] = 0; } +/* Handle a "ms_abi" or "sysv" attribute; arguments as in + struct attribute_spec.handler. */ +static tree +ix86_handle_abi_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_TYPE + && TREE_CODE (*node) != METHOD_TYPE + && TREE_CODE (*node) != FIELD_DECL + && TREE_CODE (*node) != TYPE_DECL) + { + warning (OPT_Wattributes, "%qs attribute only applies to functions", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + return NULL_TREE; + } + if (!TARGET_64BIT) + { + warning (OPT_Wattributes, "%qs attribute only available for 64-bit", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + return NULL_TREE; + } + + /* Can combine regparm with all attributes but fastcall. */ + if (is_attribute_p ("ms_abi", name)) + { + if (lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (*node))) + { + error ("ms_abi and sysv_abi attributes are not compatible"); + } + + return NULL_TREE; + } + else if (is_attribute_p ("sysv_abi", name)) + { + if (lookup_attribute ("ms_abi", TYPE_ATTRIBUTES (*node))) + { + error ("ms_abi and sysv_abi attributes are not compatible"); + } + + return NULL_TREE; + } + + return NULL_TREE; +} + /* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in struct attribute_spec.handler. */ static tree @@ -25884,6 +26068,10 @@ static const struct attribute_spec ix86_attribute_table[] = #ifdef SUBTARGET_ATTRIBUTE_TABLE SUBTARGET_ATTRIBUTE_TABLE, #endif + /* ms_abi and sysv_abi calling convention function attributes. */ + { "ms_abi", 0, 0, false, true, true, ix86_handle_abi_attribute }, + { "sysv_abi", 0, 0, false, true, true, ix86_handle_abi_attribute }, + /* End element. */ { NULL, 0, 0, false, false, false, NULL } }; @@ -25911,6 +26099,128 @@ x86_builtin_vectorization_cost (bool runtime_test) return 0; } +/* This function returns the calling abi specific va_list type node. + It returns the FNDECL specific va_list type. */ + +tree +ix86_fn_abi_va_list (tree fndecl) +{ + int abi; + + if (!TARGET_64BIT) + return va_list_type_node; + gcc_assert (fndecl != NULL_TREE); + abi = ix86_function_abi ((const_tree) fndecl); + + if (abi == MS_ABI) + return ms_va_list_type_node; + else + return sysv_va_list_type_node; +} + +/* Returns the canonical va_list type specified by TYPE. If there + is no valid TYPE provided, it return NULL_TREE. */ + +tree +ix86_canonical_va_list_type (tree type) +{ + tree wtype, htype; + + /* Resolve references and pointers to va_list type. */ + if (INDIRECT_REF_P (type)) + type = TREE_TYPE (type); + else if (POINTER_TYPE_P (type) && POINTER_TYPE_P (TREE_TYPE(type))) + type = TREE_TYPE (type); + + if (TARGET_64BIT) + { + wtype = va_list_type_node; + gcc_assert (wtype != NULL_TREE); + htype = type; + if (TREE_CODE (wtype) == ARRAY_TYPE) + { + /* If va_list is an array type, the argument may have decayed + to a pointer type, e.g. by being passed to another function. + In that case, unwrap both types so that we can compare the + underlying records. */ + if (TREE_CODE (htype) == ARRAY_TYPE + || POINTER_TYPE_P (htype)) + { + wtype = TREE_TYPE (wtype); + htype = TREE_TYPE (htype); + } + } + if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype)) + return va_list_type_node; + wtype = sysv_va_list_type_node; + gcc_assert (wtype != NULL_TREE); + htype = type; + if (TREE_CODE (wtype) == ARRAY_TYPE) + { + /* If va_list is an array type, the argument may have decayed + to a pointer type, e.g. by being passed to another function. + In that case, unwrap both types so that we can compare the + underlying records. */ + if (TREE_CODE (htype) == ARRAY_TYPE + || POINTER_TYPE_P (htype)) + { + wtype = TREE_TYPE (wtype); + htype = TREE_TYPE (htype); + } + } + if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype)) + return sysv_va_list_type_node; + wtype = ms_va_list_type_node; + gcc_assert (wtype != NULL_TREE); + htype = type; + if (TREE_CODE (wtype) == ARRAY_TYPE) + { + /* If va_list is an array type, the argument may have decayed + to a pointer type, e.g. by being passed to another function. + In that case, unwrap both types so that we can compare the + underlying records. */ + if (TREE_CODE (htype) == ARRAY_TYPE + || POINTER_TYPE_P (htype)) + { + wtype = TREE_TYPE (wtype); + htype = TREE_TYPE (htype); + } + } + if (TYPE_MAIN_VARIANT (wtype) == TYPE_MAIN_VARIANT (htype)) + return ms_va_list_type_node; + return NULL_TREE; + } + return std_canonical_va_list_type (type); +} + +/* Iterate through the target-specific builtin types for va_list. + IDX denotes the iterator, *PTREE is set to the result type of + the va_list builtin, and *PNAME to its internal type. + Returns zero if there is no element for this index, otherwise + IDX should be increased upon the next call. + Note, do not iterate a base builtin's name like __builtin_va_list. + Used from c_common_nodes_and_builtins. */ + +int +ix86_enum_va_list (int idx, const char **pname, tree *ptree) +{ + if (!TARGET_64BIT) + return 0; + switch (idx) { + case 0: + *ptree = ms_va_list_type_node; + *pname = "__builtin_ms_va_list"; + break; + case 1: + *ptree = sysv_va_list_type_node; + *pname = "__builtin_sysv_va_list"; + break; + default: + return 0; + } + return 1; +} + /* Initialize the GCC target structure. */ #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory @@ -26039,6 +26349,12 @@ x86_builtin_vectorization_cost (bool runtime_test) #undef TARGET_BUILD_BUILTIN_VA_LIST #define TARGET_BUILD_BUILTIN_VA_LIST ix86_build_builtin_va_list +#undef TARGET_FN_ABI_VA_LIST +#define TARGET_FN_ABI_VA_LIST ix86_fn_abi_va_list + +#undef TARGET_CANONICAL_VA_LIST_TYPE +#define TARGET_CANONICAL_VA_LIST_TYPE ix86_canonical_va_list_type + #undef TARGET_EXPAND_BUILTIN_VA_START #define TARGET_EXPAND_BUILTIN_VA_START ix86_va_start diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index b011885424a..d17e414eb5f 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -453,7 +453,7 @@ extern tree x86_mfence; #define TARGET_64BIT_MS_ABI (TARGET_64BIT && ix86_cfun_abi () == MS_ABI) /* Available call abi. */ -enum +enum calling_abi { SYSV_ABI = 0, MS_ABI = 1 @@ -2556,6 +2556,11 @@ struct machine_function GTY(()) #undef TARG_COND_BRANCH_COST #define TARG_COND_BRANCH_COST ix86_cost->branch_cost +/* Enum through the target specific extra va_list types. Please, do not + iterate the base va_list type name. */ +#define TARGET_ENUM_VA_LIST(IDX, PNAME, PTYPE) \ + (!TARGET_64BIT ? 0 : ix86_enum_va_list (IDX, PNAME, PTYPE)) + /* Cost of any scalar operation, excluding load and store. */ #undef TARG_SCALAR_STMT_COST #define TARG_SCALAR_STMT_COST ix86_cost->scalar_stmt_cost diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c67cf467bc9..6c06184f879 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -289,7 +289,7 @@ ;; Main data type used by the insn (define_attr "mode" - "unknown,none,QI,HI,SI,DI,SF,DF,XF,TI,V4SF,V2DF,V2SF,V1DF" + "unknown,none,QI,HI,SI,DI,TI,SF,DF,XF,TF,V4SF,V2DF,V2SF,V1DF" (const_string "unknown")) ;; The CPU unit operations uses. @@ -3311,6 +3311,34 @@ (const_string "TI"))] (const_string "DI")))]) +(define_insn "*pushtf_sse" + [(set (match_operand:TF 0 "push_operand" "=<,<,<") + (match_operand:TF 1 "general_no_elim_operand" "x,Fo,*r"))] + "TARGET_SSE2" +{ + /* This insn should be already split before reg-stack. */ + gcc_unreachable (); +} + [(set_attr "type" "multi") + (set_attr "unit" "sse,*,*") + (set_attr "mode" "TF,SI,SI")]) + +(define_split + [(set (match_operand:TF 0 "push_operand" "") + (match_operand:TF 1 "general_operand" ""))] + "TARGET_SSE2 && reload_completed + && !SSE_REG_P (operands[1])" + [(const_int 0)] + "ix86_split_long_move (operands); DONE;") + +(define_split + [(set (match_operand:TF 0 "push_operand" "") + (match_operand:TF 1 "any_fp_register_operand" ""))] + "TARGET_SSE2" + [(set (reg:P SP_REG) (plus:P (reg:P SP_REG) (const_int -16))) + (set (mem:TF (reg:P SP_REG)) (match_dup 1))] + "") + (define_split [(set (match_operand 0 "nonimmediate_operand" "") (match_operand 1 "general_operand" ""))] diff --git a/gcc/config/i386/libgcc-x86_64-glibc.ver b/gcc/config/i386/libgcc-glibc.ver index fa5d1a6dba2..be791745b43 100644 --- a/gcc/config/i386/libgcc-x86_64-glibc.ver +++ b/gcc/config/i386/libgcc-glibc.ver @@ -5,6 +5,20 @@ # to defer implementation of these routines to libgcc.so via DT_AUXILIARY. %ifndef __x86_64__ +%exclude { + __divdi3 + __moddi3 + __udivdi3 + __umoddi3 + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + %inherit GCC_3.0 GLIBC_2.0 GLIBC_2.0 { # Sampling of DImode arithmetic used by (at least) i386 and m68k. @@ -24,16 +38,18 @@ GLIBC_2.0 { } %endif -% 128 bit long double support was introduced with GCC 4.3.0. -% These lines make the symbols to get a @@GCC_4.3.0 attached. +# 128 bit long double support was introduced with GCC 4.3.0 to 64bit +# and with GCC 4.4.0 to 32bit. These lines make the symbols to get +# a @@GCC_4.3.0 or @@GCC_4.4.0 attached. -%ifdef __x86_64__ %exclude { __addtf3 + __divtc3 __divtf3 __eqtf2 __extenddftf2 __extendsftf2 + __extendxftf2 __fixtfdi __fixtfsi __fixtfti @@ -47,21 +63,45 @@ GLIBC_2.0 { __floatunsitf __floatuntitf __getf2 + __gttf2 __letf2 + __lttf2 + __multc3 __multf3 __negtf2 + __netf2 + __powitf2 __subtf3 __trunctfdf2 __trunctfsf2 + __trunctfxf2 __unordtf2 } +%ifdef __x86_64__ +# Those symbols had improper versions when they were added to gcc 4.3.0. +# We corrected the default version to GCC_4.3.0. But we keep the old +# version for backward binary compatibility. +GCC_3.0 { + __gttf2 + __lttf2 + __netf2 +} + +GCC_4.0.0 { + __divtc3 + __multc3 + __powitf2 +} + GCC_4.3.0 { __addtf3 + __divtc3 __divtf3 __eqtf2 __extenddftf2 __extendsftf2 + __extendxftf2 __fixtfdi __fixtfsi __fixtfti @@ -75,12 +115,51 @@ GCC_4.3.0 { __floatunsitf __floatuntitf __getf2 + __gttf2 + __letf2 + __lttf2 + __multc3 + __multf3 + __negtf2 + __netf2 + __powitf2 + __subtf3 + __trunctfdf2 + __trunctfsf2 + __trunctfxf2 + __unordtf2 +} +%else +GCC_4.4.0 { + __addtf3 + __copysigntf3 + __divtc3 + __divtf3 + __eqtf2 + __extenddftf2 + __extendsftf2 + __fabstf2 + __fixtfdi + __fixtfsi + __fixunstfdi + __fixunstfsi + __floatditf + __floatsitf + __floatunditf + __floatunsitf + __getf2 + __gttf2 __letf2 + __lttf2 + __multc3 __multf3 __negtf2 + __netf2 + __powitf2 __subtf3 __trunctfdf2 __trunctfsf2 + __trunctfxf2 __unordtf2 } %endif diff --git a/gcc/config/i386/linux.h b/gcc/config/i386/linux.h index ec5dc4e2230..78326b05ec0 100644 --- a/gcc/config/i386/linux.h +++ b/gcc/config/i386/linux.h @@ -189,6 +189,12 @@ along with GCC; see the file COPYING3. If not see : "=d"(BASE)) #endif +/* Put all *tf routines in libgcc. */ +#undef LIBGCC2_HAS_TF_MODE +#define LIBGCC2_HAS_TF_MODE 1 +#define LIBGCC2_TF_CEXT q +#define TF_SIZE 113 + #undef NEED_INDICATE_EXEC_STACK #define NEED_INDICATE_EXEC_STACK 1 diff --git a/gcc/config/i386/linux64.h b/gcc/config/i386/linux64.h index 37ede613e7d..04d12cadada 100644 --- a/gcc/config/i386/linux64.h +++ b/gcc/config/i386/linux64.h @@ -91,7 +91,7 @@ along with GCC; see the file COPYING3. If not see /* Put all *tf routines in libgcc. */ #undef LIBGCC2_HAS_TF_MODE -#define LIBGCC2_HAS_TF_MODE TARGET_64BIT +#define LIBGCC2_HAS_TF_MODE 1 #define LIBGCC2_TF_CEXT q #define TF_SIZE 113 diff --git a/gcc/config/i386/sfp-machine.h b/gcc/config/i386/sfp-machine.h index 190e3cb0e81..f2df869653f 100644 --- a/gcc/config/i386/sfp-machine.h +++ b/gcc/config/i386/sfp-machine.h @@ -1,143 +1,5 @@ -#define _FP_W_TYPE_SIZE 64 -#define _FP_W_TYPE unsigned long -#define _FP_WS_TYPE signed long -#define _FP_I_TYPE long - -typedef int TItype __attribute__ ((mode (TI))); -typedef unsigned int UTItype __attribute__ ((mode (TI))); - -#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype)) - -/* The type of the result of a floating point comparison. This must - match `__libgcc_cmp_return__' in GCC for the target. */ -typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); -#define CMPtype __gcc_CMPtype - -#define _FP_MUL_MEAT_Q(R,X,Y) \ - _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) - -#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) - -#define _FP_NANFRAC_S _FP_QNANBIT_S -#define _FP_NANFRAC_D _FP_QNANBIT_D -#define _FP_NANFRAC_E _FP_QNANBIT_E, 0 -#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0 -#define _FP_NANSIGN_S 1 -#define _FP_NANSIGN_D 1 -#define _FP_NANSIGN_E 1 -#define _FP_NANSIGN_Q 1 - -#define _FP_KEEPNANFRACP 1 - -/* Here is something Intel misdesigned: the specs don't define - the case where we have two NaNs with same mantissas, but - different sign. Different operations pick up different NaNs. */ -#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ - do { \ - if (_FP_FRAC_GT_##wc(X, Y) \ - || (_FP_FRAC_EQ_##wc(X,Y) && (OP == '+' || OP == '*'))) \ - { \ - R##_s = X##_s; \ - _FP_FRAC_COPY_##wc(R,X); \ - } \ - else \ - { \ - R##_s = Y##_s; \ - _FP_FRAC_COPY_##wc(R,Y); \ - } \ - R##_c = FP_CLS_NAN; \ - } while (0) - -#define FP_EX_INVALID 0x01 -#define FP_EX_DENORM 0x02 -#define FP_EX_DIVZERO 0x04 -#define FP_EX_OVERFLOW 0x08 -#define FP_EX_UNDERFLOW 0x10 -#define FP_EX_INEXACT 0x20 - -struct fenv -{ - unsigned short int __control_word; - unsigned short int __unused1; - unsigned short int __status_word; - unsigned short int __unused2; - unsigned short int __tags; - unsigned short int __unused3; - unsigned int __eip; - unsigned short int __cs_selector; - unsigned int __opcode:11; - unsigned int __unused4:5; - unsigned int __data_offset; - unsigned short int __data_selector; - unsigned short int __unused5; -}; - -#define FP_HANDLE_EXCEPTIONS \ - do { \ - if (_fex & FP_EX_INVALID) \ - { \ - float f = 0.0; \ - __asm__ __volatile__ ("divss %0, %0 " : : "x" (f)); \ - } \ - if (_fex & FP_EX_DIVZERO) \ - { \ - float f = 1.0, g = 0.0; \ - __asm__ __volatile__ ("divss %1, %0" : : "x" (f), "x" (g)); \ - } \ - if (_fex & FP_EX_OVERFLOW) \ - { \ - struct fenv temp; \ - __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ - temp.__status_word |= FP_EX_OVERFLOW; \ - __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ - __asm__ __volatile__ ("fwait"); \ - } \ - if (_fex & FP_EX_UNDERFLOW) \ - { \ - struct fenv temp; \ - __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ - temp.__status_word |= FP_EX_UNDERFLOW; \ - __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ - __asm__ __volatile__ ("fwait"); \ - } \ - if (_fex & FP_EX_INEXACT) \ - { \ - struct fenv temp; \ - __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ - temp.__status_word |= FP_EX_INEXACT; \ - __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ - __asm__ __volatile__ ("fwait"); \ - } \ - } while (0) - -#define FP_RND_NEAREST 0 -#define FP_RND_ZERO 0xc00 -#define FP_RND_PINF 0x800 -#define FP_RND_MINF 0x400 - -#define _FP_DECL_EX \ - unsigned short _fcw __attribute__ ((unused)) = FP_RND_NEAREST - -#define FP_INIT_ROUNDMODE \ - do { \ - __asm__ ("fnstcw %0" : "=m" (_fcw)); \ - } while (0) - -#define FP_ROUNDMODE (_fcw & 0xc00) - -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 - -#define __BYTE_ORDER __LITTLE_ENDIAN - -/* Define ALIASNAME as a strong alias for NAME. */ -#if defined __MACH__ -/* Mach-O doesn't support aliasing. If these functions ever return - anything but CMPtype we need to revisit this... */ -#define strong_alias(name, aliasname) \ - CMPtype aliasname (TFtype a, TFtype b) { return name(a, b); } +#ifdef __x86_64__ +#include "config/i386/64/sfp-machine.h" #else -# define strong_alias(name, aliasname) _strong_alias(name, aliasname) -# define _strong_alias(name, aliasname) \ - extern __typeof (name) aliasname __attribute__ ((alias (#name))); +#include "config/i386/32/sfp-machine.h" #endif diff --git a/gcc/config/i386/sol2-c1.asm b/gcc/config/i386/sol2-c1.asm index af1ab3141f0..4c30a16f4a7 100644 --- a/gcc/config/i386/sol2-c1.asm +++ b/gcc/config/i386/sol2-c1.asm @@ -41,7 +41,6 @@ ! information obtained by single stepping executables on other i386 SVR4 ! implementations. This file is the first thing linked into any executable. - .file "crt1.s" .ident "GNU C crt1.s" .weak _cleanup .weak _DYNAMIC diff --git a/gcc/config/i386/sol2-ci.asm b/gcc/config/i386/sol2-ci.asm index c7a17445fcc..1846a1eab89 100644 --- a/gcc/config/i386/sol2-ci.asm +++ b/gcc/config/i386/sol2-ci.asm @@ -37,7 +37,6 @@ ! sections. It is linked in before the values-Xx.o files and also before ! crtbegin.o. - .file "crti.s" .ident "GNU C crti.s" .section .init diff --git a/gcc/config/i386/sol2-cn.asm b/gcc/config/i386/sol2-cn.asm index acd266ac070..37f7362d5db 100644 --- a/gcc/config/i386/sol2-cn.asm +++ b/gcc/config/i386/sol2-cn.asm @@ -36,7 +36,6 @@ ! This file just supplies returns for the .init and .fini sections. It is ! linked in after all other files. - .file "crtn.o" .ident "GNU C crtn.o" .section .init diff --git a/gcc/config/i386/sol2-gc1.asm b/gcc/config/i386/sol2-gc1.asm index abe9ed6aae6..994326a6b00 100644 --- a/gcc/config/i386/sol2-gc1.asm +++ b/gcc/config/i386/sol2-gc1.asm @@ -45,7 +45,6 @@ ! to allow program profiling, by calling monstartup on entry and _mcleanup ! on exit - .file "gcrt1.s" .ident "GNU C gcrt1.s" .weak _DYNAMIC .text diff --git a/gcc/config/i386/t-darwin b/gcc/config/i386/t-darwin index 6feb48a20a4..fb5bbe78c04 100644 --- a/gcc/config/i386/t-darwin +++ b/gcc/config/i386/t-darwin @@ -2,6 +2,3 @@ MULTILIB_OPTIONS = m64 MULTILIB_DIRNAMES = x86_64 LIB2_SIDITI_CONV_FUNCS=yes LIB2FUNCS_EXTRA = $(srcdir)/config/darwin-64.c - -softfp_wrap_start := '\#ifdef __x86_64__' -softfp_wrap_end := '\#endif' diff --git a/gcc/config/i386/t-darwin64 b/gcc/config/i386/t-darwin64 index 2e55cb786d7..5143e3819dc 100644 --- a/gcc/config/i386/t-darwin64 +++ b/gcc/config/i386/t-darwin64 @@ -1,5 +1,2 @@ LIB2_SIDITI_CONV_FUNCS=yes LIB2FUNCS_EXTRA = $(srcdir)/config/darwin-64.c - -softfp_wrap_start := '\#ifdef __x86_64__' -softfp_wrap_end := '\#endif' diff --git a/gcc/config/i386/t-fprules-softfp64 b/gcc/config/i386/t-fprules-softfp index 0b0068f9053..0b0068f9053 100644 --- a/gcc/config/i386/t-fprules-softfp64 +++ b/gcc/config/i386/t-fprules-softfp diff --git a/gcc/config/i386/t-linux b/gcc/config/i386/t-linux new file mode 100644 index 00000000000..4c6bb51e3b8 --- /dev/null +++ b/gcc/config/i386/t-linux @@ -0,0 +1,5 @@ +# On 64bit we do not need any exports for glibc for 64-bit libgcc_s. +# Need to support TImode for x86. Override the settings from +# t-slibgcc-elf-ver and t-linux +SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver \ + $(srcdir)/config/i386/libgcc-glibc.ver diff --git a/gcc/config/i386/t-linux64 b/gcc/config/i386/t-linux64 index 0490d7812e1..36378d87e0b 100644 --- a/gcc/config/i386/t-linux64 +++ b/gcc/config/i386/t-linux64 @@ -1,9 +1,3 @@ -# On x86-64 we do not need any exports for glibc for 64-bit libgcc_s, -# override the settings -# from t-slibgcc-elf-ver and t-linux -SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver \ - $(srcdir)/config/i386/libgcc-x86_64-glibc.ver - # On Debian, Ubuntu and other derivative distributions, the 32bit libraries # are found in /lib32 and /usr/lib32, /lib64 and /usr/lib64 are symlinks to # /lib and /usr/lib, while other distributions install libraries into /lib64 @@ -21,6 +15,3 @@ INSTALL_LIBGCC = install-multilib EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o \ crtbeginT.o crtprec32.o crtprec64.o crtprec80.o \ crtfastmath.o - -softfp_wrap_start := '\#ifdef __x86_64__' -softfp_wrap_end := '\#endif' diff --git a/gcc/config/ia64/crti.asm b/gcc/config/ia64/crti.asm index a2d1e1221cc..773f154ad42 100644 --- a/gcc/config/ia64/crti.asm +++ b/gcc/config/ia64/crti.asm @@ -35,8 +35,6 @@ # .init sections. Users may put any desired instructions in those # sections. - .file "crti.asm" - .section ".init" .align 16 .global _init diff --git a/gcc/config/ia64/crtn.asm b/gcc/config/ia64/crtn.asm index 52ec47c582e..c72bd696661 100644 --- a/gcc/config/ia64/crtn.asm +++ b/gcc/config/ia64/crtn.asm @@ -35,8 +35,6 @@ # fact return. Users may put any desired instructions in those sections. # This file is the last thing linked into any executable. - .file "crtn.asm" - .section ".init" ;; mov ar.pfs = r34 diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index de39ab12946..e93ae31b0bd 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -1119,8 +1119,8 @@ ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead) } else { - p[0] = (((unsigned HOST_WIDE_INT) l[3]) << 32) + l[2]; - p[1] = (((unsigned HOST_WIDE_INT) l[1]) << 32) + l[0]; + p[0] = (((unsigned HOST_WIDE_INT) l[1]) << 32) + l[0]; + p[1] = (((unsigned HOST_WIDE_INT) l[3]) << 32) + l[2]; } out[0] = GEN_INT (p[0]); out[1] = GEN_INT (p[1]); diff --git a/gcc/config/libgcc-glibc.ver b/gcc/config/libgcc-glibc.ver index 837c1a7ee56..264828b17c0 100644 --- a/gcc/config/libgcc-glibc.ver +++ b/gcc/config/libgcc-glibc.ver @@ -4,6 +4,20 @@ # maintain enough binary compatibility to allow future versions of glibc # to defer implementation of these routines to libgcc.so via DT_AUXILIARY. +%exclude { + __divdi3 + __moddi3 + __udivdi3 + __umoddi3 + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + %inherit GCC_3.0 GLIBC_2.0 GLIBC_2.0 { # Sampling of DImode arithmetic used by (at least) i386 and m68k. diff --git a/gcc/config/m32r/libgcc-glibc.ver b/gcc/config/m32r/libgcc-glibc.ver index 450c4b60e92..977c3346604 100644 --- a/gcc/config/m32r/libgcc-glibc.ver +++ b/gcc/config/m32r/libgcc-glibc.ver @@ -8,6 +8,16 @@ # because GLIBC_2.0 does not exist on this architecture, as the first # ever glibc release on the platform was GLIBC_2.3. +%exclude { + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + %inherit GCC_3.0 GLIBC_2.3 GLIBC_2.3 { __register_frame diff --git a/gcc/config/m68hc11/larith.asm b/gcc/config/m68hc11/larith.asm index 7bb06915fca..c24a41c2646 100644 --- a/gcc/config/m68hc11/larith.asm +++ b/gcc/config/m68hc11/larith.asm @@ -33,8 +33,6 @@ Boston, MA 02110-1301, USA. */ This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. */ - .file "larith.asm" - #ifdef __HAVE_SHORT_INT__ .mode mshort #else diff --git a/gcc/config/m68hc11/m68hc11-crt0.S b/gcc/config/m68hc11/m68hc11-crt0.S index 5e92680b97d..c8644694918 100644 --- a/gcc/config/m68hc11/m68hc11-crt0.S +++ b/gcc/config/m68hc11/m68hc11-crt0.S @@ -34,7 +34,6 @@ Boston, MA 02110-1301, USA. */ ;----------------------------------------- ; startup code ;----------------------------------------- - .file "crt0.s" #ifdef __HAVE_SHORT_INT__ .mode mshort diff --git a/gcc/config/m68k/crti.s b/gcc/config/m68k/crti.s index 760c2e85b0d..ac085419165 100644 --- a/gcc/config/m68k/crti.s +++ b/gcc/config/m68k/crti.s @@ -31,7 +31,6 @@ Boston, MA 02110-1301, USA. */ * sections. It is linked in before crtbegin.o. */ - .file "crti.o" .ident "GNU C crti.o" .section .init diff --git a/gcc/config/m68k/crtn.s b/gcc/config/m68k/crtn.s index 98c8bed3476..83f605347aa 100644 --- a/gcc/config/m68k/crtn.s +++ b/gcc/config/m68k/crtn.s @@ -31,7 +31,6 @@ Boston, MA 02110-1301, USA. */ * It is linked in after all other files. */ - .file "crtn.o" .ident "GNU C crtn.o" .section .init diff --git a/gcc/config/m68k/lb1sf68.asm b/gcc/config/m68k/lb1sf68.asm index d09213fc033..e03b7b30d87 100644 --- a/gcc/config/m68k/lb1sf68.asm +++ b/gcc/config/m68k/lb1sf68.asm @@ -129,10 +129,11 @@ Boston, MA 02110-1301, USA. */ #else /* __PIC__ */ - /* Common for -mid-shared-libary and -msep-data */ + /* Common for Linux and uClinux, the latter with either + -mid-shared-library or -msep-data. */ .macro PICCALL addr -#if defined (__mcoldfire__) && !defined (__mcfisab__) +#if defined (__mcoldfire__) && !defined (__mcfisab__) && !defined (__mcfisac__) lea \addr-.-8,a0 jsr pc@(a0) #else @@ -141,6 +142,9 @@ Boston, MA 02110-1301, USA. */ .endm .macro PICJUMP addr + /* ISA C has no bra.l instruction, and since this assembly file + gets assembled into multiple object files, we avoid the + bra instruction entirely. */ #if defined (__mcoldfire__) && !defined (__mcfisab__) lea \addr-.-8,a0 jmp pc@(a0) @@ -149,7 +153,11 @@ Boston, MA 02110-1301, USA. */ #endif .endm -# if defined(__ID_SHARED_LIBRARY__) +# if defined (__uClinux__) + + /* Versions for uClinux */ + +# if defined(__ID_SHARED_LIBRARY__) /* -mid-shared-library versions */ @@ -163,7 +171,7 @@ Boston, MA 02110-1301, USA. */ movel \sym@GOT(\areg), sp@- .endm -# else /* !__ID_SHARED_LIBRARY__ */ +# else /* !__ID_SHARED_LIBRARY__ */ /* Versions for -msep-data */ @@ -175,7 +183,25 @@ Boston, MA 02110-1301, USA. */ movel \sym@GOT(a5), sp@- .endm -# endif /* !__ID_SHARED_LIBRARY__ */ +# endif + +# else /* !__uClinux__ */ + + /* Versions for Linux */ + + .macro PICLEA sym, reg + movel #_GLOBAL_OFFSET_TABLE_@GOTPC, \reg + lea (-6, pc, \reg), \reg + movel \sym@GOT(\reg), \reg + .endm + + .macro PICPEA sym, areg + movel #_GLOBAL_OFFSET_TABLE_@GOTPC, \areg + lea (-6, pc, \areg), \areg + movel \sym@GOT(\areg), sp@- + .endm + +# endif #endif /* __PIC__ */ diff --git a/gcc/config/m68k/m68k-devices.def b/gcc/config/m68k/m68k-devices.def index 7b06e35b737..fb5cde3b451 100644 --- a/gcc/config/m68k/m68k-devices.def +++ b/gcc/config/m68k/m68k-devices.def @@ -63,7 +63,11 @@ There is a bit of duplication between devices in the same family, but this approach makes scripting easier. We keep each entry on - a single line for the same reason. */ + a single line for the same reason. + + As the compiler does not (currently) generate MAC or EMAC commands, + we do not need separate multilibs for cores that only differ in + their MAC functionality. */ /* 680x0 series processors. */ M68K_DEVICE ("68000", m68000, "68000", "68000", 68000, isa_00, 0) @@ -86,31 +90,31 @@ M68K_DEVICE ("5206", mcf5206, "5206", "5206", cfv2, isa_a, 0) M68K_DEVICE ("5206e", mcf5206e, "5206e", "5206e", cfv2, isa_a, FL_CF_HWDIV | FL_CF_MAC) M68K_DEVICE ("5207", mcf5207, "5208", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("5208", mcf5208, "5208", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -M68K_DEVICE ("5210a", mcf5210a, "5211a", "5213", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) -M68K_DEVICE ("5211a", mcf5211a, "5211a", "5213", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) -M68K_DEVICE ("5211", mcf5211, "5213", "5213", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) -M68K_DEVICE ("5212", mcf5212, "5213", "5213", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) -M68K_DEVICE ("5213", mcf5213, "5213", "5213", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) +M68K_DEVICE ("5210a", mcf5210a, "5211a", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) +M68K_DEVICE ("5211a", mcf5211a, "5211a", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) +M68K_DEVICE ("5211", mcf5211, "5213", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) +M68K_DEVICE ("5212", mcf5212, "5213", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) +M68K_DEVICE ("5213", mcf5213, "5213", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) M68K_DEVICE ("5214", mcf5214, "5216", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("5216", mcf5216, "5216", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -M68K_DEVICE ("52221", mcf52221, "52223", "5213", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) -M68K_DEVICE ("52223", mcf52223, "52223", "5213", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) +M68K_DEVICE ("52221", mcf52221, "52223", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) +M68K_DEVICE ("52223", mcf52223, "52223", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) M68K_DEVICE ("52230", mcf52230, "52235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("52231", mcf52231, "52235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("52232", mcf52232, "52235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("52233", mcf52233, "52235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("52234", mcf52234, "52235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("52235", mcf52235, "52235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -M68K_DEVICE ("5224", mcf5224, "5225", "5213", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) -M68K_DEVICE ("5225", mcf5225, "5225", "5213", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) +M68K_DEVICE ("5224", mcf5224, "5225", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) +M68K_DEVICE ("5225", mcf5225, "5225", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_MAC) M68K_DEVICE ("5232", mcf5232, "5235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("5233", mcf5233, "5235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("5234", mcf5234, "5235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("5235", mcf5235, "5235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("523x", mcf523x, "5235", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) -M68K_DEVICE ("5249", mcf5249, "5249", "5249", cfv2, isa_a, FL_CF_HWDIV | FL_CF_EMAC) -M68K_DEVICE ("5250", mcf5250, "5250", "5249", cfv2, isa_a, FL_CF_HWDIV | FL_CF_EMAC) -M68K_DEVICE ("5253", mcf5253, "5253", "5249", cfv2, isa_a, FL_CF_HWDIV | FL_CF_EMAC) +M68K_DEVICE ("5249", mcf5249, "5249", "5206e", cfv2, isa_a, FL_CF_HWDIV | FL_CF_EMAC) +M68K_DEVICE ("5250", mcf5250, "5250", "5206e", cfv2, isa_a, FL_CF_HWDIV | FL_CF_EMAC) +M68K_DEVICE ("5253", mcf5253, "5253", "5206e", cfv2, isa_a, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("5270", mcf5270, "5271", "5208", cfv2, isa_aplus, FL_CF_HWDIV | FL_CF_EMAC) M68K_DEVICE ("5271", mcf5271, "5271", "5208", cfv2, isa_aplus, FL_CF_HWDIV) M68K_DEVICE ("5272", mcf5272, "5272", "5206e", cfv2, isa_a, FL_CF_HWDIV | FL_CF_MAC) diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 046132088bc..1853073af81 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -148,7 +148,7 @@ static bool m68k_save_reg (unsigned int regno, bool interrupt_handler); static bool m68k_ok_for_sibcall_p (tree, tree); static bool m68k_rtx_costs (rtx, int, int, int *); #if M68K_HONOR_TARGET_STRICT_ALIGNMENT -static bool m68k_return_in_memory (tree, tree); +static bool m68k_return_in_memory (const_tree, const_tree); #endif @@ -4627,7 +4627,7 @@ m68k_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) /* Worker function for TARGET_RETURN_IN_MEMORY. */ #if M68K_HONOR_TARGET_STRICT_ALIGNMENT static bool -m68k_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED) +m68k_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) { enum machine_mode mode = TYPE_MODE (type); diff --git a/gcc/config/m68k/t-cf b/gcc/config/m68k/t-cf index 697946654af..7bf8e11ee82 100644 --- a/gcc/config/m68k/t-cf +++ b/gcc/config/m68k/t-cf @@ -2,3 +2,6 @@ M68K_MLIB_CPU += && (CPU ~ "^mcf") M68K_ARCH := cf +# Do not stamp the multilibs with a MAC type, as we never use those +# instructions in compiler-generated code. +MULTILIB_EXTRA_OPTS += Wa,-mno-mac diff --git a/gcc/config/m68k/t-linux b/gcc/config/m68k/t-linux new file mode 100644 index 00000000000..f46d3a873d5 --- /dev/null +++ b/gcc/config/m68k/t-linux @@ -0,0 +1,11 @@ +EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o + +# Only include multilibs for CPUs with an MMU. +M68K_MLIB_CPU += && match(FLAGS, "FL_MMU") + +# This rule uses MULTILIB_MATCHES to generate a definition of +# SYSROOT_SUFFIX_SPEC. +sysroot-suffix.h: $(srcdir)/config/m68k/print-sysroot-suffix.sh + $(SHELL) $(srcdir)/config/m68k/print-sysroot-suffix.sh \ + "$(SYSTEM_HEADER_DIR)/../.." "$(MULTILIB_MATCHES)" \ + "$(MULTILIB_OPTIONS)" > $@ diff --git a/gcc/config/mcore/crti.asm b/gcc/config/mcore/crti.asm index dac882d7ad8..281424f8e67 100644 --- a/gcc/config/mcore/crti.asm +++ b/gcc/config/mcore/crti.asm @@ -37,8 +37,6 @@ # .init sections. Users may put any desired instructions in those # sections. - .file "crti.asm" - .section ".init" .global _init .type _init,@function diff --git a/gcc/config/mcore/crtn.asm b/gcc/config/mcore/crtn.asm index 87f2455305b..dc46ca4e576 100644 --- a/gcc/config/mcore/crtn.asm +++ b/gcc/config/mcore/crtn.asm @@ -37,8 +37,6 @@ # fact return. Users may put any desired instructions in those sections. # This file is the last thing linked into any executable. - .file "crtn.asm" - .section ".init" .align 4 diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 48ba54b1cef..e8d51bcd40e 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -442,7 +442,7 @@ const struct mips_rtx_cost_data *mips_cost; static int mips_base_target_flags; /* True if MIPS16 is the default mode. */ -static bool mips_base_mips16; +bool mips_base_mips16; /* The ambient values of other global variables. */ static int mips_base_delayed_branch; /* flag_delayed_branch */ @@ -12333,8 +12333,14 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, } /* The last argument passed to mips_set_mips16_mode, or negative if the - function hasn't been called yet. */ -static GTY(()) int was_mips16_p = -1; + function hasn't been called yet. + + There are two copies of this information. One is saved and restored + by the PCH process while the other is specific to this compiler + invocation. The information calculated by mips_set_mips16_mode + is invalid unless the two variables are the same. */ +static int was_mips16_p = -1; +static GTY(()) int was_mips16_pch_p = -1; /* Set up the target-dependent global state so that it matches the current function's ISA mode. */ @@ -12342,7 +12348,8 @@ static GTY(()) int was_mips16_p = -1; static void mips_set_mips16_mode (int mips16_p) { - if (mips16_p == was_mips16_p) + if (mips16_p == was_mips16_p + && mips16_p == was_mips16_pch_p) return; /* Restore base settings of various flags. */ @@ -12417,11 +12424,12 @@ mips_set_mips16_mode (int mips16_p) /* (Re)initialize MIPS target internals for new ISA. */ mips_init_relocs (); - if (was_mips16_p >= 0) + if (was_mips16_p >= 0 || was_mips16_pch_p >= 0) /* Reinitialize target-dependent state. */ target_reinit (); was_mips16_p = mips16_p; + was_mips16_pch_p = mips16_p; } /* Implement TARGET_SET_CURRENT_FUNCTION. Decide whether the current @@ -12627,6 +12635,10 @@ mips_override_options (void) { int i, start, regno, mode; + /* Process flags as though we were generating non-MIPS16 code. */ + mips_base_mips16 = TARGET_MIPS16; + target_flags &= ~MASK_MIPS16; + #ifdef SUBTARGET_OVERRIDE_OPTIONS SUBTARGET_OVERRIDE_OPTIONS; #endif @@ -12772,14 +12784,6 @@ mips_override_options (void) target_flags &= ~MASK_ABICALLS; } - /* MIPS16 cannot generate PIC yet. */ - if (TARGET_MIPS16 && (flag_pic || TARGET_ABICALLS)) - { - sorry ("MIPS16 PIC"); - target_flags &= ~MASK_ABICALLS; - flag_pic = flag_pie = flag_shlib = 0; - } - if (TARGET_ABICALLS) /* We need to set flag_pic for executables as well as DSOs because we may reference symbols that are not defined in @@ -12807,7 +12811,7 @@ mips_override_options (void) { if (!TARGET_GPOPT) { - if (!TARGET_MIPS16 && !TARGET_EXPLICIT_RELOCS) + if (!TARGET_EXPLICIT_RELOCS) error ("%<-mno-gpopt%> needs %<-mexplicit-relocs%>"); TARGET_LOCAL_SDATA = false; @@ -12911,7 +12915,6 @@ mips_override_options (void) target_flags |= MASK_FIX_R4400; /* Save base state of options. */ - mips_base_mips16 = TARGET_MIPS16; mips_base_target_flags = target_flags; mips_base_delayed_branch = flag_delayed_branch; mips_base_schedule_insns = flag_schedule_insns; @@ -12921,8 +12924,11 @@ mips_override_options (void) mips_base_align_jumps = align_jumps; mips_base_align_functions = align_functions; - /* Now select the ISA mode. */ - mips_set_mips16_mode (mips_base_mips16); + /* Now select the ISA mode. + + Do all CPP-sensitive stuff in non-MIPS16 mode; we'll switch to + MIPS16 mode afterwards if need be. */ + mips_set_mips16_mode (false); /* We call dbr_schedule from within mips_reorg. */ flag_delayed_branch = 0; diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 781528d01ba..8518a86233b 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -390,7 +390,7 @@ enum mips_code_readable_setting { else \ builtin_define ("__mips_fpr=32"); \ \ - if (TARGET_MIPS16) \ + if (mips_base_mips16) \ builtin_define ("__mips16"); \ \ if (TARGET_MIPS3D) \ @@ -3232,6 +3232,7 @@ extern int mips_abi; /* which ABI to use */ extern const struct mips_cpu_info *mips_arch_info; extern const struct mips_cpu_info *mips_tune_info; extern const struct mips_rtx_cost_data *mips_cost; +extern bool mips_base_mips16; extern enum mips_code_readable_setting mips_code_readable; #endif diff --git a/gcc/config/mips/t-libgcc-mips16 b/gcc/config/mips/t-libgcc-mips16 index 819f5c6fc21..d37b6eef539 100644 --- a/gcc/config/mips/t-libgcc-mips16 +++ b/gcc/config/mips/t-libgcc-mips16 @@ -19,3 +19,6 @@ LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \ _m16stubsc9 _m16stubsc10 \ _m16stubdc0 _m16stubdc1 _m16stubdc2 _m16stubdc5 _m16stubdc6 \ _m16stubdc9 _m16stubdc10 + +LIBGCC_SYNC = yes +LIBGCC_SYNC_CFLAGS = -mno-mips16 diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 0529a86a68c..238d35276e4 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -694,8 +694,7 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) orig = XEXP (XEXP (orig, 0), 0); /* Extract CODE_LABEL. */ orig = XEXP (orig, 0); - REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, orig, - REG_NOTES (insn)); + add_reg_note (insn, REG_LABEL_OPERAND, orig); LABEL_NUSES (orig)++; } crtl->uses_pic_offset_table = 1; diff --git a/gcc/config/rs6000/crtresfpr.asm b/gcc/config/rs6000/crtresfpr.asm index aaa4b968049..fedff803bf8 100644 --- a/gcc/config/rs6000/crtresfpr.asm +++ b/gcc/config/rs6000/crtresfpr.asm @@ -38,7 +38,6 @@ /* Do any initializations needed for the eabi environment */ - .file "crtresfpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/crtresgpr.asm b/gcc/config/rs6000/crtresgpr.asm index 928341d7624..7e73a1a8fe3 100644 --- a/gcc/config/rs6000/crtresgpr.asm +++ b/gcc/config/rs6000/crtresgpr.asm @@ -38,7 +38,6 @@ /* Do any initializations needed for the eabi environment */ - .file "crtresgpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/crtresxfpr.asm b/gcc/config/rs6000/crtresxfpr.asm index 2a734866f07..a12683308f4 100644 --- a/gcc/config/rs6000/crtresxfpr.asm +++ b/gcc/config/rs6000/crtresxfpr.asm @@ -38,7 +38,6 @@ /* Do any initializations needed for the eabi environment */ - .file "crtresxfpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/crtresxgpr.asm b/gcc/config/rs6000/crtresxgpr.asm index 1bab865c452..c4593ae5cd3 100644 --- a/gcc/config/rs6000/crtresxgpr.asm +++ b/gcc/config/rs6000/crtresxgpr.asm @@ -38,7 +38,6 @@ /* Do any initializations needed for the eabi environment */ - .file "crtresxgpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/crtsavfpr.asm b/gcc/config/rs6000/crtsavfpr.asm index f3d708f6200..b6eaaab50bf 100644 --- a/gcc/config/rs6000/crtsavfpr.asm +++ b/gcc/config/rs6000/crtsavfpr.asm @@ -38,7 +38,6 @@ /* Do any initializations needed for the eabi environment */ - .file "crtsavfpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/crtsavgpr.asm b/gcc/config/rs6000/crtsavgpr.asm index 0e244316fa6..0bf594d98e2 100644 --- a/gcc/config/rs6000/crtsavgpr.asm +++ b/gcc/config/rs6000/crtsavgpr.asm @@ -38,7 +38,6 @@ /* Do any initializations needed for the eabi environment */ - .file "crtsavgpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/crtsavres.asm b/gcc/config/rs6000/crtsavres.asm index 498759d27d8..7fea5232885 100644 --- a/gcc/config/rs6000/crtsavres.asm +++ b/gcc/config/rs6000/crtsavres.asm @@ -37,7 +37,6 @@ /* Do any initializations needed for the eabi environment */ - .file "crtsavres.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtres32gpr.asm b/gcc/config/rs6000/e500crtres32gpr.asm index bd5f825447f..31856feaf71 100644 --- a/gcc/config/rs6000/e500crtres32gpr.asm +++ b/gcc/config/rs6000/e500crtres32gpr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtres32gpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtres64gpr.asm b/gcc/config/rs6000/e500crtres64gpr.asm index 73ab506710c..17660920fac 100644 --- a/gcc/config/rs6000/e500crtres64gpr.asm +++ b/gcc/config/rs6000/e500crtres64gpr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtres64gpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtres64gprctr.asm b/gcc/config/rs6000/e500crtres64gprctr.asm index 93b5963321a..9dbc7ed9c3d 100644 --- a/gcc/config/rs6000/e500crtres64gprctr.asm +++ b/gcc/config/rs6000/e500crtres64gprctr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtres64gprctr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtrest32gpr.asm b/gcc/config/rs6000/e500crtrest32gpr.asm index 42f81d689f6..e2442c98be1 100644 --- a/gcc/config/rs6000/e500crtrest32gpr.asm +++ b/gcc/config/rs6000/e500crtrest32gpr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtrest32gpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtrest64gpr.asm b/gcc/config/rs6000/e500crtrest64gpr.asm index cf7092c7a28..acc8349eebf 100644 --- a/gcc/config/rs6000/e500crtrest64gpr.asm +++ b/gcc/config/rs6000/e500crtrest64gpr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtrest64gpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtresx32gpr.asm b/gcc/config/rs6000/e500crtresx32gpr.asm index 9fba08b5511..cab0d48d738 100644 --- a/gcc/config/rs6000/e500crtresx32gpr.asm +++ b/gcc/config/rs6000/e500crtresx32gpr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtresx32gpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtresx64gpr.asm b/gcc/config/rs6000/e500crtresx64gpr.asm index e6a24e94b35..6a57ada0507 100644 --- a/gcc/config/rs6000/e500crtresx64gpr.asm +++ b/gcc/config/rs6000/e500crtresx64gpr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtresx64gpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtsav32gpr.asm b/gcc/config/rs6000/e500crtsav32gpr.asm index 6cf97956ccc..a606617b8ec 100644 --- a/gcc/config/rs6000/e500crtsav32gpr.asm +++ b/gcc/config/rs6000/e500crtsav32gpr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtsav32gpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtsav64gpr.asm b/gcc/config/rs6000/e500crtsav64gpr.asm index 6a2b0fac82a..7d8c191cf4a 100644 --- a/gcc/config/rs6000/e500crtsav64gpr.asm +++ b/gcc/config/rs6000/e500crtsav64gpr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtsav64gpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtsav64gprctr.asm b/gcc/config/rs6000/e500crtsav64gprctr.asm index 1261bb06ed8..99f72faea54 100644 --- a/gcc/config/rs6000/e500crtsav64gprctr.asm +++ b/gcc/config/rs6000/e500crtsav64gprctr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtsav64gprctr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtsavg32gpr.asm b/gcc/config/rs6000/e500crtsavg32gpr.asm index d648817a763..3c8d759dcd2 100644 --- a/gcc/config/rs6000/e500crtsavg32gpr.asm +++ b/gcc/config/rs6000/e500crtsavg32gpr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtsavg32gpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtsavg64gpr.asm b/gcc/config/rs6000/e500crtsavg64gpr.asm index 7a60a84f2ec..a81faf87380 100644 --- a/gcc/config/rs6000/e500crtsavg64gpr.asm +++ b/gcc/config/rs6000/e500crtsavg64gpr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtsavg64gpr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/e500crtsavg64gprctr.asm b/gcc/config/rs6000/e500crtsavg64gprctr.asm index 1d978ec2793..bdc598b0871 100644 --- a/gcc/config/rs6000/e500crtsavg64gprctr.asm +++ b/gcc/config/rs6000/e500crtsavg64gprctr.asm @@ -34,7 +34,6 @@ * the executable file might be covered by the GNU General Public License. */ - .file "e500crtsavg64gprctr.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/eabi-ci.asm b/gcc/config/rs6000/eabi-ci.asm index d32120f13f1..6b332783766 100644 --- a/gcc/config/rs6000/eabi-ci.asm +++ b/gcc/config/rs6000/eabi-ci.asm @@ -36,7 +36,6 @@ Boston, MA 02110-1301, USA. /* This file just supplies labeled starting points for the .got* and other special sections. It is linked in first before other modules. */ - .file "crti.s" .ident "GNU C crti.s" #include <ppc-asm.h> diff --git a/gcc/config/rs6000/eabi-cn.asm b/gcc/config/rs6000/eabi-cn.asm index fcfea4d133e..df7baeb34f5 100644 --- a/gcc/config/rs6000/eabi-cn.asm +++ b/gcc/config/rs6000/eabi-cn.asm @@ -36,7 +36,6 @@ Boston, MA 02110-1301, USA. /* This file just supplies labeled ending points for the .got* and other special sections. It is linked in last after other modules. */ - .file "crtn.s" .ident "GNU C crtn.s" #ifndef __powerpc64__ diff --git a/gcc/config/rs6000/eabi.asm b/gcc/config/rs6000/eabi.asm index b5d4505d9ed..347fd7b02e1 100644 --- a/gcc/config/rs6000/eabi.asm +++ b/gcc/config/rs6000/eabi.asm @@ -36,7 +36,6 @@ /* Do any initializations needed for the eabi environment */ - .file "eabi.asm" .section ".text" #include "ppc-asm.h" diff --git a/gcc/config/rs6000/host-darwin.c b/gcc/config/rs6000/host-darwin.c index bb50f0edfd3..333f4884e1b 100644 --- a/gcc/config/rs6000/host-darwin.c +++ b/gcc/config/rs6000/host-darwin.c @@ -1,5 +1,6 @@ /* Darwin/powerpc host-specific hook definitions. - Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 + Free Software Foundation, Inc. This file is part of GCC. @@ -138,7 +139,7 @@ darwin_rs6000_extra_signals (void) struct sigaction sact; stack_t sigstk; - sigstk.ss_sp = xmalloc (SIGSTKSZ); + sigstk.ss_sp = (char*)xmalloc (SIGSTKSZ); sigstk.ss_size = SIGSTKSZ; sigstk.ss_flags = 0; if (sigaltstack (&sigstk, NULL) < 0) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 5efde36de8d..8fe16464285 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -10745,26 +10745,6 @@ operands[0] = XEXP (operands[0], 0); - if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT - && flag_pic - && GET_CODE (operands[0]) == SYMBOL_REF - && !SYMBOL_REF_LOCAL_P (operands[0])) - { - rtx call; - rtvec tmp; - - tmp = gen_rtvec (3, - gen_rtx_CALL (VOIDmode, - gen_rtx_MEM (SImode, operands[0]), - operands[1]), - gen_rtx_USE (VOIDmode, operands[2]), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_REG (Pmode, LR_REGNO))); - call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp)); - use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx); - DONE; - } - if (GET_CODE (operands[0]) != SYMBOL_REF || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0])) || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0)) @@ -10816,29 +10796,6 @@ operands[1] = XEXP (operands[1], 0); - if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT - && flag_pic - && GET_CODE (operands[1]) == SYMBOL_REF - && !SYMBOL_REF_LOCAL_P (operands[1])) - { - rtx call; - rtvec tmp; - - tmp = gen_rtvec (3, - gen_rtx_SET (VOIDmode, - operands[0], - gen_rtx_CALL (VOIDmode, - gen_rtx_MEM (SImode, - operands[1]), - operands[2])), - gen_rtx_USE (VOIDmode, operands[3]), - gen_rtx_CLOBBER (VOIDmode, - gen_rtx_REG (Pmode, LR_REGNO))); - call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp)); - use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx); - DONE; - } - if (GET_CODE (operands[1]) != SYMBOL_REF || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1])) || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0)) @@ -11094,7 +11051,7 @@ [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg") (set_attr "length" "4,4,8,8")]) -(define_insn "*call_nonlocal_sysv<mode>" +(define_insn_and_split "*call_nonlocal_sysv<mode>" [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s")) (match_operand 1 "" "g,g")) (use (match_operand:SI 2 "immediate_operand" "O,n")) @@ -11114,18 +11071,51 @@ #else if (DEFAULT_ABI == ABI_V4 && flag_pic) { - if (TARGET_SECURE_PLT && flag_pic == 2) - /* The magic 32768 offset here and in the other sysv call insns - corresponds to the offset of r30 in .got2, as given by LCTOC1. - See sysv4.h:toc_section. */ - return "bl %z0+32768@plt"; - else - return "bl %z0@plt"; + gcc_assert (!TARGET_SECURE_PLT); + return "bl %z0@plt"; } else return "bl %z0"; #endif } + "DEFAULT_ABI == ABI_V4 + && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[0]) + && (INTVAL (operands[2]) & CALL_LONG) == 0" + [(parallel [(call (mem:SI (match_dup 0)) + (match_dup 1)) + (use (match_dup 2)) + (use (match_dup 3)) + (clobber (reg:SI LR_REGNO))])] +{ + operands[3] = pic_offset_table_rtx; +} + [(set_attr "type" "branch,branch") + (set_attr "length" "4,8")]) + +(define_insn "*call_nonlocal_sysv_secure<mode>" + [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s")) + (match_operand 1 "" "g,g")) + (use (match_operand:SI 2 "immediate_operand" "O,n")) + (use (match_operand:SI 3 "register_operand" "r,r")) + (clobber (reg:SI LR_REGNO))] + "(DEFAULT_ABI == ABI_V4 + && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[0]) + && (INTVAL (operands[2]) & CALL_LONG) == 0)" +{ + if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS) + output_asm_insn ("crxor 6,6,6", operands); + + else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) + output_asm_insn ("creqv 6,6,6", operands); + + if (flag_pic == 2) + /* The magic 32768 offset here and in the other sysv call insns + corresponds to the offset of r30 in .got2, as given by LCTOC1. + See sysv4.h:toc_section. */ + return "bl %z0+32768@plt"; + else + return "bl %z0@plt"; +} [(set_attr "type" "branch,branch") (set_attr "length" "4,8")]) @@ -11149,7 +11139,7 @@ [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg") (set_attr "length" "4,4,8,8")]) -(define_insn "*call_value_nonlocal_sysv<mode>" +(define_insn_and_split "*call_value_nonlocal_sysv<mode>" [(set (match_operand 0 "" "") (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s,s")) (match_operand 2 "" "g,g"))) @@ -11170,15 +11160,50 @@ #else if (DEFAULT_ABI == ABI_V4 && flag_pic) { - if (TARGET_SECURE_PLT && flag_pic == 2) - return "bl %z1+32768@plt"; - else - return "bl %z1@plt"; + gcc_assert (!TARGET_SECURE_PLT); + return "bl %z1@plt"; } else return "bl %z1"; #endif } + "DEFAULT_ABI == ABI_V4 + && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[1]) + && (INTVAL (operands[3]) & CALL_LONG) == 0" + [(parallel [(set (match_dup 0) + (call (mem:SI (match_dup 1)) + (match_dup 2))) + (use (match_dup 3)) + (use (match_dup 4)) + (clobber (reg:SI LR_REGNO))])] +{ + operands[4] = pic_offset_table_rtx; +} + [(set_attr "type" "branch,branch") + (set_attr "length" "4,8")]) + +(define_insn "*call_value_nonlocal_sysv_secure<mode>" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s,s")) + (match_operand 2 "" "g,g"))) + (use (match_operand:SI 3 "immediate_operand" "O,n")) + (use (match_operand:SI 4 "register_operand" "r,r")) + (clobber (reg:SI LR_REGNO))] + "(DEFAULT_ABI == ABI_V4 + && TARGET_SECURE_PLT && flag_pic && !SYMBOL_REF_LOCAL_P (operands[1]) + && (INTVAL (operands[3]) & CALL_LONG) == 0)" +{ + if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS) + output_asm_insn ("crxor 6,6,6", operands); + + else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) + output_asm_insn ("creqv 6,6,6", operands); + + if (flag_pic == 2) + return "bl %z1+32768@plt"; + else + return "bl %z1@plt"; +} [(set_attr "type" "branch,branch") (set_attr "length" "4,8")]) @@ -11391,10 +11416,8 @@ if (DEFAULT_ABI == ABI_V4 && flag_pic) { - if (TARGET_SECURE_PLT && flag_pic == 2) - return \"b %z0+32768@plt\"; - else - return \"b %z0@plt\"; + gcc_assert (!TARGET_SECURE_PLT); + return \"b %z0@plt\"; } else return \"b %z0\"; @@ -11443,10 +11466,8 @@ if (DEFAULT_ABI == ABI_V4 && flag_pic) { - if (TARGET_SECURE_PLT && flag_pic == 2) - return \"b %z1+32768@plt\"; - else - return \"b %z1@plt\"; + gcc_assert (!TARGET_SECURE_PLT); + return \"b %z1@plt\"; } else return \"b %z1\"; diff --git a/gcc/config/rs6000/sol-ci.asm b/gcc/config/rs6000/sol-ci.asm index 35e3b8e5c35..528a72d2d8d 100644 --- a/gcc/config/rs6000/sol-ci.asm +++ b/gcc/config/rs6000/sol-ci.asm @@ -36,7 +36,6 @@ # This file just supplies labeled starting points for the .got* and other # special sections. It is linked in first before other modules. - .file "scrti.s" .ident "GNU C scrti.s" #ifndef __powerpc64__ diff --git a/gcc/config/rs6000/sol-cn.asm b/gcc/config/rs6000/sol-cn.asm index b9ef4443464..de144c07a79 100644 --- a/gcc/config/rs6000/sol-cn.asm +++ b/gcc/config/rs6000/sol-cn.asm @@ -36,7 +36,6 @@ # This file just supplies labeled ending points for the .got* and other # special sections. It is linked in last after other modules. - .file "scrtn.s" .ident "GNU C scrtn.s" #ifndef __powerpc64__ diff --git a/gcc/config/rs6000/tramp.asm b/gcc/config/rs6000/tramp.asm index cd61f1d7efd..b620df32d00 100644 --- a/gcc/config/rs6000/tramp.asm +++ b/gcc/config/rs6000/tramp.asm @@ -35,7 +35,6 @@ /* Set up trampolines. */ - .file "tramp.asm" .section ".text" #include "ppc-asm.h" #include "config.h" diff --git a/gcc/config/s390/libgcc-glibc.ver b/gcc/config/s390/libgcc-glibc.ver index e9413d0fff1..ab6eedcf683 100644 --- a/gcc/config/s390/libgcc-glibc.ver +++ b/gcc/config/s390/libgcc-glibc.ver @@ -9,6 +9,20 @@ # ever glibc release on the platform was GLIBC_2.2. %ifndef __s390x__ +%exclude { + __divdi3 + __moddi3 + __udivdi3 + __umoddi3 + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + %inherit GCC_3.0 GLIBC_2.0 GLIBC_2.0 { __divdi3 @@ -27,6 +41,16 @@ GLIBC_2.0 { %endif %ifdef __s390x__ +%exclude { + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + %inherit GCC_3.0 GLIBC_2.2 GLIBC_2.2 { __register_frame diff --git a/gcc/config/sh/libgcc-glibc.ver b/gcc/config/sh/libgcc-glibc.ver index 734d3d6bfe1..11ef379effa 100644 --- a/gcc/config/sh/libgcc-glibc.ver +++ b/gcc/config/sh/libgcc-glibc.ver @@ -8,6 +8,16 @@ # because GLIBC_2.0 does not exist on this architecture, as the first # ever glibc release on the platform was GLIBC_2.2. +%exclude { + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + %inherit GCC_3.0 GLIBC_2.2 GLIBC_2.2 { __register_frame @@ -18,4 +28,3 @@ GLIBC_2.2 { __frame_state_for __register_frame_info_table } - diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 71419ec61de..380705104ee 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -4983,10 +4983,8 @@ sh_reorg (void) or pseudo-op. */ label = gen_label_rtx (); - REG_NOTES (link) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, label, - REG_NOTES (link)); - REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, label, - REG_NOTES (insn)); + add_reg_note (link, REG_LABEL_OPERAND, label); + add_reg_note (insn, REG_LABEL_OPERAND, label); if (rescan) { scan = link; @@ -5000,9 +4998,7 @@ sh_reorg (void) && reg_mentioned_p (reg, scan)) || ((reg2 = sfunc_uses_reg (scan)) && REGNO (reg2) == REGNO (reg)))) - REG_NOTES (scan) - = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, label, - REG_NOTES (scan)); + add_reg_note (scan, REG_LABEL_OPERAND, label); } while (scan != dies); } diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 2ff4a81f9b6..5204847abc5 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler for Renesas / SuperH SH. Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. Contributed by Steve Chamberlain (sac@cygnus.com). Improved by Jim Wilson (wilson@cygnus.com). @@ -712,8 +712,8 @@ do { \ to the pressure on R0. */ \ /* Enable sched1 for SH4; ready queue will be reordered by \ the target hooks when pressure is high. We can not do this for \ - SH3 and lower as they give spill failures for R0. */ \ - if (!TARGET_HARD_SH4) \ + PIC, SH3 and lower as they give spill failures for R0. */ \ + if (!TARGET_HARD_SH4 || flag_pic) \ flag_schedule_insns = 0; \ /* ??? Current exception handling places basic block boundaries \ after call_insns. It causes the high pressure on R0 and gives \ diff --git a/gcc/config/sparc/libgcc-sparc-glibc.ver b/gcc/config/sparc/libgcc-sparc-glibc.ver index ed280fe05a7..8f50c0d5886 100644 --- a/gcc/config/sparc/libgcc-sparc-glibc.ver +++ b/gcc/config/sparc/libgcc-sparc-glibc.ver @@ -4,6 +4,20 @@ # maintain enough binary compatibility to allow future versions of glibc # to defer implementation of these routines to libgcc.so via DT_AUXILIARY. +%exclude { + __divdi3 + __moddi3 + __udivdi3 + __umoddi3 + __register_frame + __register_frame_table + __deregister_frame + __register_frame_info + __deregister_frame_info + __frame_state_for + __register_frame_info_table +} + %ifdef __arch64__ %define GLIBC_VER GLIBC_2.2 %else diff --git a/gcc/config/sparc/sol2-ci.asm b/gcc/config/sparc/sol2-ci.asm index 5726d62d994..d1ddc8412ff 100644 --- a/gcc/config/sparc/sol2-ci.asm +++ b/gcc/config/sparc/sol2-ci.asm @@ -40,8 +40,6 @@ ! This file is linked in before the Values-Xx.o files and also before ! crtbegin, with which perhaps it should be merged. - .file "crti.s" - .section ".init" .proc 022 .global _init diff --git a/gcc/config/sparc/sol2-cn.asm b/gcc/config/sparc/sol2-cn.asm index 6e2fb2c6e49..aad6f568058 100644 --- a/gcc/config/sparc/sol2-cn.asm +++ b/gcc/config/sparc/sol2-cn.asm @@ -37,8 +37,6 @@ ! fact return. Users may put any desired instructions in those sections. ! This file is the last thing linked into any executable. - .file "crtn.s" - .section ".init" .align 4 diff --git a/gcc/config/sync.c b/gcc/config/sync.c new file mode 100644 index 00000000000..ec60ef0a1a4 --- /dev/null +++ b/gcc/config/sync.c @@ -0,0 +1,185 @@ +/* Out-of-line libgcc versions of __sync_* builtins. */ +/* Copyright (C) 2008 Free Software Foundation, Inc. + +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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +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, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ + +/* This file is used by targets whose makefiles define LIBGCC_SYNC + to "yes". It is compiled with LIBGCC_SYNC_CFLAGS and provides + out-of-line versions of all relevant __sync_* primitives. + + These routines are intended for targets like MIPS that have two + ISA encodings (the "normal" ISA and the MIPS16 ISA). The normal + ISA provides full synchronization capabilities but the MIPS16 ISA + has no encoding for them. MIPS16 code must therefore call external + non-MIPS16 implementations of the __sync_* routines. + + The file is compiled once for each routine. The following __foo + routines are selected by defining a macro called L<foo>: + + __sync_synchronize + + The following __foo_N routines are selected by defining FN=foo + and SIZE=N: + + __sync_fetch_and_add_N + __sync_fetch_and_sub_N + __sync_fetch_and_or_N + __sync_fetch_and_and_N + __sync_fetch_and_xor_N + __sync_fetch_and_nand_N + __sync_add_and_fetch_N + __sync_sub_and_fetch_N + __sync_or_and_fetch_N + __sync_and_and_fetch_N + __sync_xor_and_fetch_N + __sync_nand_and_fetch_N + __sync_bool_compare_and_swap_N + __sync_val_compare_and_swap_N + __sync_lock_test_and_set_N + + SIZE can be 1, 2, 4, 8 or 16. __foo_N is omitted if the target does + not provide __sync_compare_and_swap_N. + + Note that __sync_lock_release does not fall back on external + __sync_lock_release_N functions. The default implementation + of __sync_lock_release is a call to __sync_synchronize followed + by a store of zero, so we don't need separate library functions + for it. */ + +#if defined FN + +/* Define macros for each __sync_* function type. Each macro defines a + local function called <NAME>_<UNITS> that acts like __<NAME>_<UNITS>. + TYPE is a type that has UNITS bytes. */ + +#define DEFINE_V_PV(NAME, UNITS, TYPE) \ + static TYPE \ + NAME##_##UNITS (TYPE *ptr, TYPE value) \ + { \ + return __##NAME (ptr, value); \ + } + +#define DEFINE_V_PVV(NAME, UNITS, TYPE) \ + static TYPE \ + NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2) \ + { \ + return __##NAME (ptr, value1, value2); \ + } + +#define DEFINE_BOOL_PVV(NAME, UNITS, TYPE) \ + static _Bool \ + NAME##_##UNITS (TYPE *ptr, TYPE value1, TYPE value2) \ + { \ + return __##NAME (ptr, value1, value2); \ + } + +/* Map function names to the appropriate DEFINE_* macro. */ + +#define local_sync_fetch_and_add DEFINE_V_PV +#define local_sync_fetch_and_sub DEFINE_V_PV +#define local_sync_fetch_and_or DEFINE_V_PV +#define local_sync_fetch_and_and DEFINE_V_PV +#define local_sync_fetch_and_xor DEFINE_V_PV +#define local_sync_fetch_and_nand DEFINE_V_PV + +#define local_sync_add_and_fetch DEFINE_V_PV +#define local_sync_sub_and_fetch DEFINE_V_PV +#define local_sync_or_and_fetch DEFINE_V_PV +#define local_sync_and_and_fetch DEFINE_V_PV +#define local_sync_xor_and_fetch DEFINE_V_PV +#define local_sync_nand_and_fetch DEFINE_V_PV + +#define local_sync_bool_compare_and_swap DEFINE_BOOL_PVV +#define local_sync_val_compare_and_swap DEFINE_V_PVV + +#define local_sync_lock_test_and_set DEFINE_V_PV + +/* Define the function __<NAME>_<UNITS>, given that TYPE is a type with + UNITS bytes. */ +#define DEFINE1(NAME, UNITS, TYPE) \ + static int unused[sizeof (TYPE) == UNITS ? 1 : -1] \ + __attribute__((unused)); \ + local_##NAME (NAME, UNITS, TYPE); \ + typeof (NAME##_##UNITS) __##NAME##_##UNITS \ + __attribute__((alias (#NAME "_" #UNITS))); + +/* As above, but performing macro expansion on the arguments. */ +#define DEFINE(NAME, UNITS, TYPE) DEFINE1 (NAME, UNITS, TYPE) + +/* Find an appropriate type TYPE for SIZE and invoke DEFINE (FN, SIZE, TYPE). + + The types chosen here may be incorrect for some targets. + For example, targets with 16-byte atomicity support might not + support OImode. We would need some kind of target-specific + override if that becomes a problem. */ + +#if SIZE == 1 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 + +typedef unsigned int UQItype __attribute__((mode (QI))); +DEFINE (FN, 1, UQItype) + +#elif SIZE == 2 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 + +typedef unsigned int UHItype __attribute__((mode (HI))); +DEFINE (FN, 2, UHItype) + +#elif SIZE == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 + +typedef unsigned int USItype __attribute__((mode (SI))); +DEFINE (FN, 4, USItype) + +#elif SIZE == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 + +typedef unsigned int UDItype __attribute__((mode (DI))); +DEFINE (FN, 8, UDItype) + +#elif SIZE == 16 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 + +typedef unsigned int UOItype __attribute__((mode (OI))); +DEFINE (FN, 8, UOItype) + +#endif + +#elif __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 \ + || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 \ + || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 \ + || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 \ + || __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 + +#if defined Lsync_synchronize + +static void +sync_synchronize (void) +{ + __sync_synchronize (); +} +typeof (sync_synchronize) __sync_synchronize \ + __attribute__((alias ("sync_synchronize"))); + +#endif + +#endif diff --git a/gcc/configure b/gcc/configure index 5c64f60cea3..4f9c86a0e53 100755 --- a/gcc/configure +++ b/gcc/configure @@ -10744,10 +10744,8 @@ fi - - for ac_func in times clock kill getrlimit setrlimit atoll atoq \ - sysconf strsignal getrusage nl_langinfo scandir alphasort \ + sysconf strsignal getrusage nl_langinfo \ gettimeofday mbstowcs wcswidth mmap mincore setlocale \ clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked do @@ -10973,6 +10971,72 @@ _ACEOF fi +echo "$as_me:$LINENO: checking for caddr_t" >&5 +echo $ECHO_N "checking for caddr_t... $ECHO_C" >&6 +if test "${ac_cv_type_caddr_t+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +if ((caddr_t *) 0) + return 0; +if (sizeof (caddr_t)) + return 0; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_type_caddr_t=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_type_caddr_t=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_type_caddr_t" >&5 +echo "${ECHO_T}$ac_cv_type_caddr_t" >&6 +if test $ac_cv_type_caddr_t = yes; then + : +else + +cat >>confdefs.h <<_ACEOF +#define caddr_t char * +_ACEOF + +fi + # Try to determine the array type of the second argument of getgroups # for the target system (int or gid_t). @@ -15306,13 +15370,13 @@ if test "${lt_cv_nm_interface+set}" = set; then else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:15309: $ac_compile\"" >&5) + (eval echo "\"\$as_me:15373: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:15312: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:15376: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:15315: output\"" >&5) + (eval echo "\"\$as_me:15379: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -16367,7 +16431,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 16370 "configure"' > conftest.$ac_ext + echo '#line 16434 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -16987,11 +17051,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:16990: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17054: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:16994: \$? = $ac_status" >&5 + echo "$as_me:17058: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -17309,11 +17373,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:17312: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17376: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:17316: \$? = $ac_status" >&5 + echo "$as_me:17380: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -17414,11 +17478,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:17417: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17481: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:17421: \$? = $ac_status" >&5 + echo "$as_me:17485: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -17469,11 +17533,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:17472: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17536: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:17476: \$? = $ac_status" >&5 + echo "$as_me:17540: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -20266,7 +20330,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 20269 "configure" +#line 20333 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -20366,7 +20430,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 20369 "configure" +#line 20433 "configure" #include "confdefs.h" #if HAVE_DLFCN_H diff --git a/gcc/configure.ac b/gcc/configure.ac index c32af5ec3fe..9fc7d0b00f6 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -1294,7 +1294,7 @@ define(gcc_UNLOCKED_FUNCS, clearerr_unlocked feof_unlocked dnl fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked dnl putchar_unlocked putc_unlocked) AC_CHECK_FUNCS(times clock kill getrlimit setrlimit atoll atoq \ - sysconf strsignal getrusage nl_langinfo scandir alphasort \ + sysconf strsignal getrusage nl_langinfo \ gettimeofday mbstowcs wcswidth mmap mincore setlocale \ gcc_UNLOCKED_FUNCS) @@ -1317,6 +1317,7 @@ int main() fi AC_CHECK_TYPE(ssize_t, int) +AC_CHECK_TYPE(caddr_t, char *) # Try to determine the array type of the second argument of getgroups # for the target system (int or gid_t). diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8aff706f9db..5ef7e2e1005 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,82 @@ +2008-07-03 Richard Guenther <rguenther@suse.de> + + PR c++/36128 + * typeck.c (cp_build_function_call): Move code to verify + builtin function arguments ... + * call.c (build_cxx_call): ... here. + +2008-07-02 Jason Merrill <jason@redhat.com> + + * Make-lang.in (cp/typeck2.o): Add $(REAL_H) dependency. + + Implement WG21 N2672, Initializer List proposed wording + * cp-tree.h (enum cp_tree_index): Add CPTI_INIT_LIST_TYPE. + (struct lang_type_class): Add has_list_ctor bitfield. + (TYPE_HAS_LIST_CTOR): New macro. + (BRACE_ENCLOSED_INITIALIZER_P): Expect init_list_type_node. + (CONSTRUCTOR_IS_DIRECT_INIT): New macro. + (LOOKUP_NO_NARROWING): New macro. + (LOOKUP_NO_COPY_CTOR_CONVERSION): New macro. + * parser.c (cp_parse_braced_list): Split out from... + (cp_parser_initializer_clause): ...here. + (cp_parser_postfix_expression): Build up CONSTRUCTOR for compound + literal here. + (cp_lexer_next_token_is_not_keyword): New fn. + (cp_parser_parenthesized_expression_list): Handle { }. + (cp_parser_new_expression, cp_parser_new_initializer): Likewise. + (cp_parser_assignment_expression, cp_parser_condition): Likewise. + (cp_parser_jump_statement, cp_parser_simple_declaration): Likewise. + (cp_parser_mem_initializer, cp_parser_init_declarator): Likewise. + (cp_parser_initializer, cp_parser_functional_cast): Likewise. + (cp_parser_omp_for_loop, cp_parser_cache_group): Likewise. + (cp_parser_save_member_function_body): Likewise. + * call.c (conversion_kind): Add ck_list, ck_aggr. + (struct conversion): Add check_narrowing bitfield, conversion list. + (build_list_conv): New fn. + (build_aggr_conv): New fn. + (implicit_conversion): Call them. + (standard_conversion): Set check_narrowing if appropriate. + (add_function_candidate): Handle LOOKUP_NO_COPY_CTOR_CONVERSION. + (build_user_type_conversion_1): When converting from an init list, + we allow additional conversions except when calling a copy ctor. + (convert_like_real): Calling an explicit ctor for an init list is + ill-formed. Handle ck_list and ck_addr. Check narrowing. + (build_new_method_call): If CONSTRUCTOR_IS_DIRECT_INIT is set and + class doesn't have a list ctor, break the {} into a TREE_LIST. + (compare_ics): ck_list is better than other UDCs. + (set_up_extended_ref_temp): Split out from initialize_reference. + (is_std_init_list): New fn. + (is_list_ctor): New fn. + * decl.c (cxx_init_decl_processing): Create init_list_type_node. + (reshape_init_array_1): Pass it to build_constructor. + (reshape_init_class): Ditto. + (initialize_artificial_var): Pass the appropriate type. + (build_aggr_init_full_exprs): Split out from... + (check_initializer): ...here. Handle new semantics. + (build_init_list_var_init): New subroutine of check_initializer. + (grokdeclarator): Converting constructors can have more than one parm. + (grok_special_member_properties): Set TYPE_HAS_LIST_CTOR. + * init.c (expand_default_init): Only do digest_init for aggregates. + * rtti.c (tinfo_base_init): Pass init_list_type_node to + build_constructor_from_list. + (generic_initializer, ptr_initializer): Ditto. + (ptm_initializer, class_initializer): Ditto. + (get_pseudo_ti_init): Ditto. + * error.c (dump_type): Handle init_list_type_node. + (maybe_warn_cpp0x): New fn. + (maybe_varn_variadic_templates): Call it. + * cvt.c (ocp_convert): Handle conversion from { }. + * tree.c (build_array_of_n_type): New fn. + * typeck2.c (store_init_value): Use init_list_type_node. + (digest_init): Likewise. + (check_narrowing): New fn. + * semantics.c: (finish_compound_literal): Take CONSTRUCTOR instead + of vector of constructor elts. Handle non-aggregate types. Make + constant literals static. + * pt.c: (tsubst_copy_and_build): Adjust. + (unify): Handle { }. + * name-lookup.c (arg_assoc_type): Handle init_list_type_node. + 2008-07-01 Daniel Jacobowitz <dan@codesourcery.com> * typeck.c (comp_ptr_ttypes_real): Use vector_targets_convertible_p. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 6fced350ec4..c7877205f25 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -245,7 +245,7 @@ cp/cp-objcp-common.o : cp/cp-objcp-common.c $(CONFIG_H) $(SYSTEM_H) \ langhooks.h $(LANGHOOKS_DEF_H) $(DIAGNOSTIC_H) debug.h \ $(CXX_PRETTY_PRINT_H) cp/cp-objcp-common.h gt-cp-cp-objcp-common.h cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) toplev.h output.h \ - $(TM_P_H) $(DIAGNOSTIC_H) gt-cp-typeck2.h + $(TM_P_H) $(DIAGNOSTIC_H) gt-cp-typeck2.h $(REAL_H) cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) $(RTL_H) $(EXPR_H) \ toplev.h $(DIAGNOSTIC_H) convert.h $(C_COMMON_H) $(TARGET_H) cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) toplev.h $(RTL_H) \ diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 7f4c0168483..368d95a677f 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -54,6 +54,8 @@ typedef enum conversion_kind { ck_ref_bind, ck_user, ck_ambig, + ck_list, + ck_aggr, ck_rvalue } conversion_kind; @@ -96,6 +98,7 @@ struct conversion { being bound to an lvalue expression or an rvalue reference is being bound to an rvalue expression. */ BOOL_BITFIELD rvaluedness_matches_p: 1; + BOOL_BITFIELD check_narrowing: 1; /* The type of the expression resulting from the conversion. */ tree type; union { @@ -107,6 +110,8 @@ struct conversion { /* The expression at the beginning of the conversion chain. This variant is used only if KIND is ck_identity or ck_ambig. */ tree expr; + /* The array of conversions for an initializer_list. */ + conversion **list; } u; /* The function candidate corresponding to this conversion sequence. This field is only used if KIND is ck_user. */ @@ -174,6 +179,7 @@ static conversion *implicit_conversion (tree, tree, tree, bool, int); static conversion *standard_conversion (tree, tree, tree, bool, int); static conversion *reference_binding (tree, tree, tree, bool, int); static conversion *build_conv (conversion_kind, tree, conversion *); +static conversion *build_list_conv (tree, tree, int); static bool is_subseq (conversion *, conversion *); static conversion *maybe_handle_ref_bind (conversion **); static void maybe_handle_implicit_object (conversion **); @@ -529,9 +535,8 @@ build_conv (conversion_kind code, tree type, conversion *from) conversion *t; conversion_rank rank = CONVERSION_RANK (from); - /* We can't use buildl1 here because CODE could be USER_CONV, which - takes two arguments. In that case, the caller is responsible for - filling in the second argument. */ + /* Note that the caller is responsible for filling in t->cand for + user-defined conversions. */ t = alloc_conversion (code); t->type = type; t->u.next = from; @@ -561,6 +566,83 @@ build_conv (conversion_kind code, tree type, conversion *from) return t; } +/* Represent a conversion from CTOR, a braced-init-list, to TYPE, a + specialization of std::initializer_list<T>, if such a conversion is + possible. */ + +static conversion * +build_list_conv (tree type, tree ctor, int flags) +{ + tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (type), 0); + unsigned len = CONSTRUCTOR_NELTS (ctor); + conversion **subconvs = alloc_conversions (len); + conversion *t; + unsigned i; + tree val; + + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), i, val) + { + conversion *sub + = implicit_conversion (elttype, TREE_TYPE (val), val, + false, flags); + if (sub == NULL) + return NULL; + + subconvs[i] = sub; + } + + t = alloc_conversion (ck_list); + t->type = type; + t->u.list = subconvs; + t->rank = cr_exact; + + for (i = 0; i < len; ++i) + { + conversion *sub = subconvs[i]; + if (sub->rank > t->rank) + t->rank = sub->rank; + if (sub->user_conv_p) + t->user_conv_p = true; + if (sub->bad_p) + t->bad_p = true; + } + + return t; +} + +/* Represent a conversion from CTOR, a braced-init-list, to TYPE, an + aggregate class, if such a conversion is possible. */ + +static conversion * +build_aggr_conv (tree type, tree ctor, int flags) +{ + unsigned HOST_WIDE_INT i = 0; + conversion *c; + tree field = TYPE_FIELDS (type); + + for (; field; field = TREE_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL) + continue; + if (i < CONSTRUCTOR_NELTS (ctor)) + { + constructor_elt *ce = CONSTRUCTOR_ELT (ctor, i); + if (!can_convert_arg (TREE_TYPE (field), TREE_TYPE (ce->value), + ce->value, flags)) + return NULL; + } + else if (build_value_init (TREE_TYPE (field)) == error_mark_node) + return NULL; + } + + c = alloc_conversion (ck_aggr); + c->type = type; + c->rank = cr_exact; + c->user_conv_p = true; + c->u.next = NULL; + return c; +} + /* Build a representation of the identity conversion from EXPR to itself. The TYPE should match the type of EXPR, if EXPR is non-NULL. */ @@ -865,6 +947,9 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, else return NULL; + if (flags & LOOKUP_NO_NARROWING) + conv->check_narrowing = true; + return conv; } @@ -1296,6 +1381,10 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, if (conv) return conv; + if (is_std_init_list (to) && expr + && BRACE_ENCLOSED_INITIALIZER_P (expr)) + return build_list_conv (to, expr, flags); + if (expr != NULL_TREE && (MAYBE_CLASS_TYPE_P (from) || MAYBE_CLASS_TYPE_P (to)) @@ -1305,6 +1394,11 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, int convflags = ((flags & LOOKUP_NO_TEMP_BIND) |LOOKUP_ONLYCONVERTING); + if (CLASS_TYPE_P (to) + && !CLASSTYPE_NON_AGGREGATE (complete_type (to)) + && BRACE_ENCLOSED_INITIALIZER_P (expr)) + return build_aggr_conv (to, expr, flags); + cand = build_user_type_conversion_1 (to, expr, convflags); if (cand) conv = cand->second_conv; @@ -1431,6 +1525,7 @@ add_function_candidate (struct z_candidate **candidates, if (parmnode) { tree parmtype = TREE_VALUE (parmnode); + int lflags = flags; /* The type of the implicit object parameter ('this') for overload resolution is not always the same as for the @@ -1449,8 +1544,12 @@ add_function_candidate (struct z_candidate **candidates, parmtype = build_pointer_type (parmtype); } + if ((flags & LOOKUP_NO_COPY_CTOR_CONVERSION) + && ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn)) + lflags |= LOOKUP_NO_CONVERSION; + t = implicit_conversion (parmtype, argtype, arg, - /*c_cast_p=*/false, flags); + /*c_cast_p=*/false, lflags); } else { @@ -2607,7 +2706,18 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ctors = BASELINK_FUNCTIONS (ctors); t = build_int_cst (build_pointer_type (totype), 0); - args = build_tree_list (NULL_TREE, expr); + if (BRACE_ENCLOSED_INITIALIZER_P (expr) + && !TYPE_HAS_LIST_CTOR (totype)) + { + args = ctor_to_list (expr); + /* We still allow more conversions within an init-list. */ + flags = ((flags & ~LOOKUP_NO_CONVERSION) + /* But not for the copy ctor. */ + |LOOKUP_NO_COPY_CTOR_CONVERSION + |LOOKUP_NO_NARROWING); + } + else + args = build_tree_list (NULL_TREE, expr); /* We should never try to call the abstract or base constructor from here. */ gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)) @@ -2617,7 +2727,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) for (; ctors; ctors = OVL_NEXT (ctors)) { tree ctor = OVL_CURRENT (ctors); - if (DECL_NONCONVERTING_P (ctor)) + if (DECL_NONCONVERTING_P (ctor) + && !BRACE_ENCLOSED_INITIALIZER_P (expr)) continue; if (TREE_CODE (ctor) == TEMPLATE_DECL) @@ -4443,6 +4554,17 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, tree convfn = cand->fn; unsigned i; + /* When converting from an init list we consider explicit + constructors, but actually trying to call one is an error. */ + if (DECL_NONCONVERTING_P (convfn)) + { + if (complain & tf_error) + error ("converting to %qT from initializer list would use " + "explicit constructor %qD", totype, convfn); + else + return error_mark_node; + } + /* Set user_conv_p on the argument conversions, so rvalue/base handling knows not to allow any more UDCs. */ for (i = 0; i < cand->num_convs; ++i) @@ -4478,6 +4600,44 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, return build_user_type_conversion (totype, convs->u.expr, LOOKUP_NORMAL); + case ck_list: + { + /* Conversion to std::initializer_list<T>. */ + tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (totype), 0); + tree new_ctor = build_constructor (init_list_type_node, NULL); + unsigned len = CONSTRUCTOR_NELTS (expr); + tree array, parms, val; + unsigned ix; + + /* Convert all the elements. */ + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val) + { + tree sub = convert_like_real (convs->u.list[ix], val, fn, argnum, + 1, false, false, complain); + if (sub == error_mark_node) + return sub; + check_narrowing (TREE_TYPE (sub), val); + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor), NULL_TREE, sub); + } + /* Build up the array. */ + elttype = cp_build_qualified_type + (elttype, TYPE_QUALS (elttype) | TYPE_QUAL_CONST); + array = build_array_of_n_type (elttype, len); + array = finish_compound_literal (array, new_ctor); + + parms = build_tree_list (NULL_TREE, size_int (len)); + parms = tree_cons (NULL_TREE, decay_conversion (array), parms); + /* Call the private constructor. */ + push_deferring_access_checks (dk_no_check); + new_ctor = build_special_member_call + (NULL_TREE, complete_ctor_identifier, parms, totype, 0, complain); + pop_deferring_access_checks (); + return build_cplus_new (totype, new_ctor); + } + + case ck_aggr: + return get_target_expr (digest_init (totype, expr)); + default: break; }; @@ -4625,6 +4785,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, break; } + if (convs->check_narrowing) + check_narrowing (totype, expr); + if (issue_conversion_warnings) expr = convert_and_check (totype, expr); else @@ -5255,6 +5418,13 @@ build_cxx_call (tree fn, int nargs, tree *argarray) && cfun) cp_function_chain->can_throw = 1; + /* Check that arguments to builtin functions match the expectations. */ + if (fndecl + && DECL_BUILT_IN (fndecl) + && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL + && !check_builtin_function_arguments (fndecl, nargs, argarray)) + return error_mark_node; + /* Some built-in function calls will be evaluated at compile-time in fold (). */ fn = fold_if_not_in_template (fn); @@ -5626,6 +5796,18 @@ build_new_method_call (tree instance, tree fns, tree args, if (DECL_DESTRUCTOR_P (fn)) name = complete_dtor_identifier; + /* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form + initializer, not T({ }). If the type doesn't have a list ctor, + break apart the list into separate ctor args. */ + if (DECL_CONSTRUCTOR_P (fn) && args + && BRACE_ENCLOSED_INITIALIZER_P (TREE_VALUE (args)) + && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (args)) + && !TYPE_HAS_LIST_CTOR (basetype)) + { + gcc_assert (TREE_CHAIN (args) == NULL_TREE); + args = ctor_to_list (TREE_VALUE (args)); + } + class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE); mem_args = tree_cons (NULL_TREE, instance_ptr, args); @@ -5977,13 +6159,26 @@ compare_ics (conversion *ics1, conversion *ics2) conversion *t1; conversion *t2; - for (t1 = ics1; t1->kind != ck_user; t1 = t1->u.next) - if (t1->kind == ck_ambig) + for (t1 = ics1; t1->kind != ck_user && t1->kind != ck_list; t1 = t1->u.next) + if (t1->kind == ck_ambig || t1->kind == ck_aggr) return 0; - for (t2 = ics2; t2->kind != ck_user; t2 = t2->u.next) - if (t2->kind == ck_ambig) + for (t2 = ics2; t2->kind != ck_user && t2->kind != ck_list; t2 = t2->u.next) + if (t2->kind == ck_ambig || t2->kind == ck_aggr) return 0; + /* Conversion to std::initializer_list is better than other + user-defined conversions. */ + if (t1->kind == ck_list + || t2->kind == ck_list) + { + if (t2->kind != ck_list) + return 1; + else if (t1->kind != ck_list) + return -1; + else + return 0; + } + if (t1->cand->fn != t2->cand->fn) return 0; @@ -6815,6 +7010,76 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type) return var; } +/* EXPR is the initializer for a variable DECL of reference or + std::initializer_list type. Create, push and return a new VAR_DECL + for the initializer so that it will live as long as DECL. Any + cleanup for the new variable is returned through CLEANUP, and the + code to initialize the new variable is returned through INITP. */ + +tree +set_up_extended_ref_temp (tree decl, tree expr, tree *cleanup, tree *initp) +{ + tree init; + tree type; + tree var; + + /* Create the temporary variable. */ + type = TREE_TYPE (expr); + var = make_temporary_var_for_ref_to_temp (decl, type); + layout_decl (var, 0); + /* If the rvalue is the result of a function call it will be + a TARGET_EXPR. If it is some other construct (such as a + member access expression where the underlying object is + itself the result of a function call), turn it into a + TARGET_EXPR here. It is important that EXPR be a + TARGET_EXPR below since otherwise the INIT_EXPR will + attempt to make a bitwise copy of EXPR to initialize + VAR. */ + if (TREE_CODE (expr) != TARGET_EXPR) + expr = get_target_expr (expr); + /* Create the INIT_EXPR that will initialize the temporary + variable. */ + init = build2 (INIT_EXPR, type, var, expr); + if (at_function_scope_p ()) + { + add_decl_expr (var); + + if (TREE_STATIC (var)) + init = add_stmt_to_compound (init, register_dtor_fn (var)); + else + *cleanup = cxx_maybe_build_cleanup (var); + + /* We must be careful to destroy the temporary only + after its initialization has taken place. If the + initialization throws an exception, then the + destructor should not be run. We cannot simply + transform INIT into something like: + + (INIT, ({ CLEANUP_STMT; })) + + because emit_local_var always treats the + initializer as a full-expression. Thus, the + destructor would run too early; it would run at the + end of initializing the reference variable, rather + than at the end of the block enclosing the + reference variable. + + The solution is to pass back a cleanup expression + which the caller is responsible for attaching to + the statement tree. */ + } + else + { + rest_of_decl_compilation (var, /*toplev=*/1, at_eof); + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + static_aggregates = tree_cons (NULL_TREE, var, + static_aggregates); + } + + *initp = init; + return var; +} + /* Convert EXPR to the indicated reference TYPE, in a way suitable for initializing a variable of that TYPE. If DECL is non-NULL, it is the VAR_DECL being initialized with the EXPR. (In that case, the @@ -6919,60 +7184,7 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup) if (!real_lvalue_p (expr)) { tree init; - tree type; - - /* Create the temporary variable. */ - type = TREE_TYPE (expr); - var = make_temporary_var_for_ref_to_temp (decl, type); - layout_decl (var, 0); - /* If the rvalue is the result of a function call it will be - a TARGET_EXPR. If it is some other construct (such as a - member access expression where the underlying object is - itself the result of a function call), turn it into a - TARGET_EXPR here. It is important that EXPR be a - TARGET_EXPR below since otherwise the INIT_EXPR will - attempt to make a bitwise copy of EXPR to initialize - VAR. */ - if (TREE_CODE (expr) != TARGET_EXPR) - expr = get_target_expr (expr); - /* Create the INIT_EXPR that will initialize the temporary - variable. */ - init = build2 (INIT_EXPR, type, var, expr); - if (at_function_scope_p ()) - { - add_decl_expr (var); - - if (TREE_STATIC (var)) - init = add_stmt_to_compound (init, register_dtor_fn (var)); - else - *cleanup = cxx_maybe_build_cleanup (var); - - /* We must be careful to destroy the temporary only - after its initialization has taken place. If the - initialization throws an exception, then the - destructor should not be run. We cannot simply - transform INIT into something like: - - (INIT, ({ CLEANUP_STMT; })) - - because emit_local_var always treats the - initializer as a full-expression. Thus, the - destructor would run too early; it would run at the - end of initializing the reference variable, rather - than at the end of the block enclosing the - reference variable. - - The solution is to pass back a cleanup expression - which the caller is responsible for attaching to - the statement tree. */ - } - else - { - rest_of_decl_compilation (var, /*toplev=*/1, at_eof); - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) - static_aggregates = tree_cons (NULL_TREE, var, - static_aggregates); - } + var = set_up_extended_ref_temp (decl, expr, cleanup, &init); /* Use its address to initialize the reference variable. */ expr = build_address (var); if (base_conv_type) @@ -7003,4 +7215,39 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup) return expr; } +/* Returns true iff TYPE is some variant of std::initializer_list. */ + +bool +is_std_init_list (tree type) +{ + return (CLASS_TYPE_P (type) + && CP_TYPE_CONTEXT (type) == std_node + && strcmp (TYPE_NAME_STRING (type), "initializer_list") == 0); +} + +/* Returns true iff DECL is a list constructor: i.e. a constructor which + will accept an argument list of a single std::initializer_list<T>. */ + +bool +is_list_ctor (tree decl) +{ + tree args = FUNCTION_FIRST_USER_PARMTYPE (decl); + tree arg; + + if (!args || args == void_list_node) + return false; + + arg = non_reference (TREE_VALUE (args)); + if (!is_std_init_list (arg)) + return false; + + args = TREE_CHAIN (args); + + if (args && args != void_list_node && !TREE_PURPOSE (args)) + /* There are more non-defaulted parms. */ + return false; + + return true; +} + #include "gt-cp-call.h" diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d090d8ff0e2..ed6ae0e810a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -59,6 +59,7 @@ struct diagnostic_info; TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX) TYPE_REF_IS_RVALUE (in REFERENCE_TYPE) ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute) + CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -572,6 +573,7 @@ enum cp_tree_index CPTI_CLASS_TYPE, CPTI_UNKNOWN_TYPE, + CPTI_INIT_LIST_TYPE, CPTI_VTBL_TYPE, CPTI_VTBL_PTR_TYPE, CPTI_STD, @@ -637,6 +639,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; #define class_type_node cp_global_trees[CPTI_CLASS_TYPE] #define unknown_type_node cp_global_trees[CPTI_UNKNOWN_TYPE] +#define init_list_type_node cp_global_trees[CPTI_INIT_LIST_TYPE] #define vtbl_type_node cp_global_trees[CPTI_VTBL_TYPE] #define vtbl_ptr_type_node cp_global_trees[CPTI_VTBL_PTR_TYPE] #define std_node cp_global_trees[CPTI_STD] @@ -1126,6 +1129,7 @@ struct lang_type_class GTY(()) unsigned has_complex_assign_ref : 1; unsigned non_aggregate : 1; unsigned has_complex_dflt : 1; + unsigned has_list_ctor : 1; /* When adding a flag here, consider whether or not it ought to apply to a template instance if it applies to the template. If @@ -1134,7 +1138,7 @@ struct lang_type_class GTY(()) /* There are some bits left to fill out a 32-bit word. Keep track of this by updating the size of this bitfield whenever you add or remove a flag. */ - unsigned dummy : 11; + unsigned dummy : 10; tree primary_base; VEC(tree_pair_s,gc) *vcall_indices; @@ -1248,6 +1252,10 @@ struct lang_type GTY(()) #define TYPE_HAS_CONST_INIT_REF(NODE) \ (LANG_TYPE_CLASS_CHECK (NODE)->has_const_init_ref) +/* Nonzero if this class has an X(initializer_list<T>) constructor. */ +#define TYPE_HAS_LIST_CTOR(NODE) \ + (LANG_TYPE_CLASS_CHECK (NODE)->has_list_ctor) + /* Nonzero if this class defines an overloaded operator new. (An operator new [] doesn't count.) */ #define TYPE_HAS_NEW_OPERATOR(NODE) \ @@ -2713,7 +2721,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) /* True if NODE is a brace-enclosed initializer. */ #define BRACE_ENCLOSED_INITIALIZER_P(NODE) \ - (TREE_CODE (NODE) == CONSTRUCTOR && !TREE_TYPE (NODE)) + (TREE_CODE (NODE) == CONSTRUCTOR && TREE_TYPE (NODE) == init_list_type_node) /* True if NODE is a compound-literal, i.e., a brace-enclosed initializer cast to a particular type. */ @@ -2725,6 +2733,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) CONSTRUCTOR_ELTS (NODE)) \ && !TREE_HAS_CONSTRUCTOR (NODE)) +/* True if NODE is a init-list used as a direct-initializer, i.e. + B b{1,2}, not B b({1,2}) or B b = {1,2}. */ +#define CONSTRUCTOR_IS_DIRECT_INIT(NODE) (TREE_LANG_FLAG_0 (CONSTRUCTOR_CHECK (NODE))) + /* Nonzero means that an object of this type can not be initialized using an initializer list. */ #define CLASSTYPE_NON_AGGREGATE(NODE) \ @@ -3688,6 +3700,11 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG }; #define LOOKUP_HIDDEN (LOOKUP_PREFER_NAMESPACES << 1) /* Prefer that the lvalue be treated as an rvalue. */ #define LOOKUP_PREFER_RVALUE (LOOKUP_HIDDEN << 1) +/* We're inside an init-list, so narrowing conversions are ill-formed. */ +#define LOOKUP_NO_NARROWING (LOOKUP_PREFER_RVALUE << 1) +/* Avoid user-defined conversions for the first parameter of a copy + constructor. */ +#define LOOKUP_NO_COPY_CTOR_CONVERSION (LOOKUP_NO_NARROWING << 1) #define LOOKUP_NAMESPACES_ONLY(F) \ (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES)) @@ -4084,6 +4101,7 @@ extern tree cxx_type_promotes_to (tree); extern tree type_passed_as (tree); extern tree convert_for_arg_passing (tree, tree); extern bool is_properly_derived_from (tree, tree); +extern tree set_up_extended_ref_temp (tree, tree, tree *, tree *); extern tree initialize_reference (tree, tree, tree, tree *); extern tree make_temporary_var_for_ref_to_temp (tree, tree); extern tree strip_top_quals (tree); @@ -4092,6 +4110,8 @@ extern tree perform_direct_initialization_if_possible (tree, tree, bool, tsubst_flags_t); extern tree in_charge_arg_for_name (tree); extern tree build_cxx_call (tree, int, tree *); +extern bool is_std_init_list (tree); +extern bool is_list_ctor (tree); #ifdef ENABLE_CHECKING extern void validate_conversion_obstack (void); #endif /* ENABLE_CHECKING */ @@ -4311,6 +4331,7 @@ extern const char *language_to_string (enum languages); extern const char *class_key_or_enum_as_string (tree); extern void print_instantiation_context (void); extern void maybe_warn_variadic_templates (void); +extern void maybe_warn_cpp0x (const char *); /* in except.c */ extern void init_exception_processing (void); @@ -4622,7 +4643,7 @@ extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree); extern tree finish_unary_op_expr (enum tree_code, tree); -extern tree finish_compound_literal (tree, VEC(constructor_elt,gc) *); +extern tree finish_compound_literal (tree, tree); extern tree finish_fname (tree); extern void finish_translation_unit (void); extern tree finish_template_type_parm (tree, tree); @@ -4707,6 +4728,7 @@ extern tree build_min_non_dep_call_list (tree, tree, tree); extern tree build_cplus_new (tree, tree); extern tree get_target_expr (tree); extern tree build_cplus_array_type (tree, tree); +extern tree build_array_of_n_type (tree, int); extern tree hash_tree_cons (tree, tree, tree); extern tree hash_tree_chain (tree, tree); extern tree build_qualified_name (tree, tree, tree, bool); @@ -4861,6 +4883,7 @@ extern void complete_type_check_abstract (tree); extern int abstract_virtuals_error (tree, tree); extern tree store_init_value (tree, tree); +extern void check_narrowing (tree, tree); extern tree digest_init (tree, tree); extern tree build_scoped_ref (tree, tree, tree *); extern tree build_x_arrow (tree); @@ -4882,6 +4905,7 @@ extern tree mangle_thunk (tree, int, tree, tree); extern tree mangle_conv_op_name_for_type (tree); extern tree mangle_guard_variable (tree); extern tree mangle_ref_init_variable (tree); +extern tree mangle_compound_literal (void); /* in dump.c */ extern bool cp_dump_tree (void *, tree); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index b2c17c547db..70ef00a4fce 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -725,8 +725,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags) if (abstract_virtuals_error (NULL_TREE, type)) return error_mark_node; - if ((flags & LOOKUP_ONLYCONVERTING) - && ! (MAYBE_CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype))) + if (BRACE_ENCLOSED_INITIALIZER_P (ctor)) + ctor = perform_implicit_conversion (type, ctor, tf_warning_or_error); + else if ((flags & LOOKUP_ONLYCONVERTING) + && ! (CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype))) /* For copy-initialization, first we create a temp of the proper type with a user-defined conversion sequence, then we direct-initialize the target with the temp (see [dcl.init]). */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c6ae93e6104..a5a5574d7b4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3344,6 +3344,9 @@ cxx_init_decl_processing (void) TYPE_POINTER_TO (unknown_type_node) = unknown_type_node; TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node; + init_list_type_node = make_node (UNKNOWN_TYPE); + record_unknown_type (init_list_type_node, "init list"); + { /* Make sure we get a unique function type, so we can give its pointer type a name. (This wins for gdb.) */ @@ -4295,6 +4298,39 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup) return NULL_TREE; } +/* Subroutine of check_initializer. We're initializing a DECL of + std::initializer_list<T> TYPE from a braced-init-list INIT, and need to + extend the lifetime of the underlying array to match that of the decl, + just like for reference initialization. CLEANUP is as for + grok_reference_init. */ + +static tree +build_init_list_var_init (tree decl, tree type, tree init, tree *cleanup) +{ + tree aggr_init, array, arrtype; + init = perform_implicit_conversion (type, init, tf_warning_or_error); + aggr_init = TARGET_EXPR_INITIAL (init); + init = build2 (INIT_EXPR, type, decl, init); + + array = AGGR_INIT_EXPR_ARG (aggr_init, 1); + arrtype = TREE_TYPE (array); + STRIP_NOPS (array); + gcc_assert (TREE_CODE (array) == ADDR_EXPR); + array = TREE_OPERAND (array, 0); + /* If the array is constant, finish_compound_literal already made it a + static variable and we don't need to do anything here. */ + if (decl && TREE_CODE (array) == TARGET_EXPR) + { + tree subinit; + tree var = set_up_extended_ref_temp (decl, array, cleanup, &subinit); + var = build_address (var); + var = convert (arrtype, var); + AGGR_INIT_EXPR_ARG (aggr_init, 1) = var; + init = build2 (COMPOUND_EXPR, TREE_TYPE (init), subinit, init); + } + return init; +} + /* Designated initializers in arrays are not supported in GNU C++. The parser cannot detect this error since it does not know whether a given brace-enclosed initializer is for a class type or for an @@ -4573,7 +4609,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d) unsigned HOST_WIDE_INT index; /* The initializer for an array is always a CONSTRUCTOR. */ - new_init = build_constructor (NULL_TREE, NULL); + new_init = build_constructor (init_list_type_node, NULL); if (sized_array_p) { @@ -4668,7 +4704,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p) gcc_assert (CLASS_TYPE_P (type)); /* The initializer for a class is always a CONSTRUCTOR. */ - new_init = build_constructor (NULL_TREE, NULL); + new_init = build_constructor (init_list_type_node, NULL); field = next_initializable_field (TYPE_FIELDS (type)); if (!field) @@ -4926,6 +4962,26 @@ check_array_initializer (tree decl, tree type, tree init) return false; } +/* Subroutine of check_initializer; args are passed down from that function. + Set stmts_are_full_exprs_p to 1 across a call to build_aggr_init. */ + +static tree +build_aggr_init_full_exprs (tree decl, tree init, int flags) + +{ + int saved_stmts_are_full_exprs_p = 0; + if (building_stmt_tree ()) + { + saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); + current_stmt_tree ()->stmts_are_full_exprs_p = 1; + } + init = build_aggr_init (decl, init, flags, tf_warning_or_error); + if (building_stmt_tree ()) + current_stmt_tree ()->stmts_are_full_exprs_p = + saved_stmts_are_full_exprs_p; + return init; +} + /* Verify INIT (the initializer for DECL), and record the initialization in DECL_INITIAL, if appropriate. CLEANUP is as for grok_reference_init. @@ -4967,7 +5023,12 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) int init_len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)); if (SCALAR_TYPE_P (type)) { - if (init_len != 1) + if (init_len == 0) + { + maybe_warn_cpp0x ("extended initializer lists"); + init = build_zero_init (type, NULL_TREE, false); + } + else if (init_len != 1) { error ("scalar object %qD requires one element in initializer", decl); @@ -4975,15 +5036,6 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) return NULL_TREE; } } - else if ((cxx_dialect == cxx98) && !CP_AGGREGATE_TYPE_P (type)) - { - /* A non-aggregate that is not a scalar cannot be initialized - via an initializer-list in C++98. */ - error ("braces around initializer for non-aggregate type %qT", - type); - TREE_TYPE (decl) = error_mark_node; - return NULL_TREE; - } } if (TREE_CODE (decl) == CONST_DECL) @@ -5001,17 +5053,26 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) { /* Do not reshape constructors of vectors (they don't need to be reshaped. */ - if (TREE_CODE (init) == CONSTRUCTOR - && !COMPOUND_LITERAL_P (init) - && !TREE_TYPE (init)) /* ptrmemfunc */ + if (BRACE_ENCLOSED_INITIALIZER_P (init)) { - init = reshape_init (type, init); - - if ((*targetm.vector_opaque_p) (type)) + if (is_std_init_list (type)) + return build_init_list_var_init (decl, type, init, cleanup); + else if (TYPE_NON_AGGREGATE_CLASS (type)) + { + /* Don't reshape if the class has constructors. */ + if (cxx_dialect == cxx98) + error ("in C++98 %qD must be initialized by constructor, " + "not by %<{...}%>", + decl); + init = build_tree_list (NULL_TREE, init); + } + else if ((*targetm.vector_opaque_p) (type)) { error ("opaque vector types cannot be initialized"); init = error_mark_node; } + else + init = reshape_init (type, init); } /* If DECL has an array type without a specific bound, deduce the @@ -5021,60 +5082,26 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) if (type == error_mark_node) return NULL_TREE; - if (TREE_CODE (type) == ARRAY_TYPE && TYPE_NEEDS_CONSTRUCTING (type)) - goto initialize_aggr; - else if (CLASS_TYPE_P (type)) + if (TYPE_NEEDS_CONSTRUCTING (type) + || (CLASS_TYPE_P (type) + && !BRACE_ENCLOSED_INITIALIZER_P (init))) + return build_aggr_init_full_exprs (decl, init, flags); + else if (TREE_CODE (init) != TREE_VEC) { - if (TREE_CODE (init) == CONSTRUCTOR) - { - if (TYPE_NON_AGGREGATE_CLASS (type)) - { - error ("%qD must be initialized by constructor, " - "not by %<{...}%>", - decl); - init = error_mark_node; - } - else - goto dont_use_constructor; - } - else - { - int saved_stmts_are_full_exprs_p; - - initialize_aggr: - saved_stmts_are_full_exprs_p = 0; - if (building_stmt_tree ()) - { - saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); - current_stmt_tree ()->stmts_are_full_exprs_p = 1; - } - init = build_aggr_init (decl, init, flags, tf_warning_or_error); - if (building_stmt_tree ()) - current_stmt_tree ()->stmts_are_full_exprs_p = - saved_stmts_are_full_exprs_p; - return init; - } - } - else - { - dont_use_constructor: - if (TREE_CODE (init) != TREE_VEC) - { - init_code = store_init_value (decl, init); - if (pedantic && TREE_CODE (type) == ARRAY_TYPE - && DECL_INITIAL (decl) - && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST - && PAREN_STRING_LITERAL_P (DECL_INITIAL (decl))) - warning (0, "array %qD initialized by parenthesized string literal %qE", - decl, DECL_INITIAL (decl)); - init = NULL; - } + init_code = store_init_value (decl, init); + if (pedantic && TREE_CODE (type) == ARRAY_TYPE + && DECL_INITIAL (decl) + && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST + && PAREN_STRING_LITERAL_P (DECL_INITIAL (decl))) + warning (0, "array %qD initialized by parenthesized string literal %qE", + decl, DECL_INITIAL (decl)); + init = NULL; } } else if (DECL_EXTERNAL (decl)) ; else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type)) - goto initialize_aggr; + return build_aggr_init_full_exprs (decl, init, flags); else if (MAYBE_CLASS_TYPE_P (type)) { tree core_type = strip_array_types (type); @@ -5311,7 +5338,7 @@ initialize_artificial_var (tree decl, tree init) { gcc_assert (DECL_ARTIFICIAL (decl)); if (TREE_CODE (init) == TREE_LIST) - init = build_constructor_from_list (NULL_TREE, init); + init = build_constructor_from_list (TREE_TYPE (decl), init); gcc_assert (TREE_CODE (init) == CONSTRUCTOR); DECL_INITIAL (decl) = init; DECL_INITIALIZED_P (decl) = 1; @@ -8921,17 +8948,11 @@ grokdeclarator (const cp_declarator *declarator, DECL_NONCONVERTING_P (decl) = 1; else if (DECL_CONSTRUCTOR_P (decl)) { - /* The constructor can be called with exactly one - parameter if there is at least one parameter, and - any subsequent parameters have default arguments. + /* A constructor with no parms is not a conversion. Ignore any compiler-added parms. */ tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (decl); - if (arg_types == void_list_node - || (arg_types - && TREE_CHAIN (arg_types) - && TREE_CHAIN (arg_types) != void_list_node - && !TREE_PURPOSE (TREE_CHAIN (arg_types)))) + if (arg_types == void_list_node) DECL_NONCONVERTING_P (decl) = 1; } } @@ -9646,6 +9667,8 @@ grok_special_member_properties (tree decl) } else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl))) TYPE_HAS_DEFAULT_CONSTRUCTOR (class_type) = 1; + else if (is_list_ctor (decl)) + TYPE_HAS_LIST_CTOR (class_type) = 1; } else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR) { diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 55e620a6b54..80aa6e962d2 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -284,7 +284,10 @@ dump_type (tree t, int flags) switch (TREE_CODE (t)) { case UNKNOWN_TYPE: - pp_identifier (cxx_pp, "<unresolved overloaded function type>"); + if (t == init_list_type_node) + pp_identifier (cxx_pp, "<brace-enclosed initializer list>"); + else + pp_identifier (cxx_pp, "<unresolved overloaded function type>"); break; case TREE_LIST: @@ -2674,13 +2677,20 @@ cp_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, report_diagnostic (&diagnostic); } -/* Warn about the use of variadic templates when appropriate. */ +/* Warn about the use of C++0x features when appropriate. */ void -maybe_warn_variadic_templates (void) +maybe_warn_cpp0x (const char* str) { if ((cxx_dialect == cxx98) && !in_system_header) /* We really want to suppress this warning in system headers, because libstdc++ uses variadic templates even when we aren't in C++0x mode. */ - pedwarn ("ISO C++ does not include variadic templates"); + pedwarn ("%s only available with -std=c++0x", str); +} + +/* Warn about the use of variadic templates when appropriate. */ +void +maybe_warn_variadic_templates (void) +{ + maybe_warn_cpp0x ("variadic templates"); } diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 0c38a7fcb0c..3e9e612f2b4 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1334,10 +1334,10 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, to run a new constructor; and catching an exception, where we have already built up the constructor call so we could wrap it in an exception region. */; - else if (BRACE_ENCLOSED_INITIALIZER_P (init)) + else if (BRACE_ENCLOSED_INITIALIZER_P (init) + && CP_AGGREGATE_TYPE_P (type)) { /* A brace-enclosed initializer for an aggregate. */ - gcc_assert (CP_AGGREGATE_TYPE_P (type)); init = digest_init (type, init); } else diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 290cb7030b5..e42f60afba7 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4639,7 +4639,8 @@ arg_assoc_type (struct arg_lookup *k, tree type) case TYPENAME_TYPE: return false; case LANG_TYPE: - gcc_assert (type == unknown_type_node); + gcc_assert (type == unknown_type_node + || type == init_list_type_node); return false; case TYPE_PACK_EXPANSION: return arg_assoc_type (k, PACK_EXPANSION_PATTERN (type)); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 7d530f50714..2323c672166 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -529,6 +529,14 @@ cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword) return cp_lexer_peek_token (lexer)->keyword == keyword; } +/* Return true if the next token is not the indicated KEYWORD. */ + +static inline bool +cp_lexer_next_token_is_not_keyword (cp_lexer* lexer, enum rid keyword) +{ + return cp_lexer_peek_token (lexer)->keyword != keyword; +} + /* Return true if the next token is a keyword for a decl-specifier. */ static bool @@ -1743,6 +1751,8 @@ static tree cp_parser_initializer (cp_parser *, bool *, bool *); static tree cp_parser_initializer_clause (cp_parser *, bool *); +static tree cp_parser_braced_list + (cp_parser*, bool*); static VEC(constructor_elt,gc) *cp_parser_initializer_list (cp_parser *, bool *); @@ -1965,7 +1975,7 @@ static bool cp_parser_optional_template_keyword (cp_parser *); static void cp_parser_pre_parsed_nested_name_specifier (cp_parser *); -static void cp_parser_cache_group +static bool cp_parser_cache_group (cp_parser *, enum cpp_ttype, unsigned); static void cp_parser_parse_tentatively (cp_parser *); @@ -4534,7 +4544,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, } /* Form the representation of the compound-literal. */ postfix_expression - = finish_compound_literal (type, initializer_list); + = (finish_compound_literal + (type, build_constructor (init_list_type_node, + initializer_list))); break; } } @@ -5070,10 +5082,19 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, } else { + bool expr_non_constant_p; + /* Parse the next assignment-expression. */ - if (non_constant_p) + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + /* A braced-init-list. */ + maybe_warn_cpp0x ("extended initializer lists"); + expr = cp_parser_braced_list (parser, &expr_non_constant_p); + if (non_constant_p && expr_non_constant_p) + *non_constant_p = true; + } + else if (non_constant_p) { - bool expr_non_constant_p; expr = (cp_parser_constant_expression (parser, /*allow_non_constant_p=*/true, &expr_non_constant_p)); @@ -5535,8 +5556,9 @@ cp_parser_new_expression (cp_parser* parser) else type = cp_parser_new_type_id (parser, &nelts); - /* If the next token is a `(', then we have a new-initializer. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + /* If the next token is a `(' or '{', then we have a new-initializer. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN) + || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) initializer = cp_parser_new_initializer (parser); else initializer = NULL_TREE; @@ -5748,6 +5770,7 @@ cp_parser_direct_new_declarator (cp_parser* parser) new-initializer: ( expression-list [opt] ) + braced-init-list Returns a representation of the expression-list. If there is no expression-list, VOID_ZERO_NODE is returned. */ @@ -5757,9 +5780,18 @@ cp_parser_new_initializer (cp_parser* parser) { tree expression_list; - expression_list = (cp_parser_parenthesized_expression_list - (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true, - /*non_constant_p=*/NULL)); + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + bool expr_non_constant_p; + maybe_warn_cpp0x ("extended initializer lists"); + expression_list = cp_parser_braced_list (parser, &expr_non_constant_p); + CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; + expression_list = build_tree_list (NULL_TREE, expression_list); + } + else + expression_list = (cp_parser_parenthesized_expression_list + (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true, + /*non_constant_p=*/NULL)); if (!expression_list) expression_list = void_zero_node; @@ -6208,10 +6240,14 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p) = cp_parser_assignment_operator_opt (parser); if (assignment_operator != ERROR_MARK) { - tree rhs; + bool non_constant_p; /* Parse the right-hand side of the assignment. */ - rhs = cp_parser_assignment_expression (parser, cast_p); + tree rhs = cp_parser_initializer_clause (parser, &non_constant_p); + + if (BRACE_ENCLOSED_INITIALIZER_P (rhs)) + maybe_warn_cpp0x ("extended initializer lists"); + /* An assignment may not appear in a constant-expression. */ if (cp_parser_non_integral_constant_expression (parser, @@ -7124,7 +7160,8 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p) condition: expression - type-specifier-seq declarator = assignment-expression + type-specifier-seq declarator = initializer-clause + type-specifier-seq declarator braced-init-list GNU Extension: @@ -7170,31 +7207,47 @@ cp_parser_condition (cp_parser* parser) attributes = cp_parser_attributes_opt (parser); /* Parse the asm-specification. */ asm_specification = cp_parser_asm_specification_opt (parser); - /* If the next token is not an `=', then we might still be + /* If the next token is not an `=' or '{', then we might still be looking at an expression. For example: if (A(a).x) looks like a decl-specifier-seq and a declarator -- but then there is no `=', so this is an expression. */ - cp_parser_require (parser, CPP_EQ, "%<=%>"); - /* If we did see an `=', then we are looking at a declaration + if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ) + && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) + cp_parser_simulate_error (parser); + + /* If we did see an `=' or '{', then we are looking at a declaration for sure. */ if (cp_parser_parse_definitely (parser)) { tree pushed_scope; bool non_constant_p; + bool flags = LOOKUP_ONLYCONVERTING; /* Create the declaration. */ decl = start_decl (declarator, &type_specifiers, /*initialized_p=*/true, attributes, /*prefix_attributes=*/NULL_TREE, &pushed_scope); - /* Parse the assignment-expression. */ - initializer - = cp_parser_constant_expression (parser, - /*allow_non_constant_p=*/true, - &non_constant_p); + + /* Parse the initializer. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + initializer = cp_parser_braced_list (parser, &non_constant_p); + CONSTRUCTOR_IS_DIRECT_INIT (initializer) = 1; + flags = 0; + } + else + { + /* Consume the `='. */ + cp_lexer_consume_token (parser->lexer); + initializer = cp_parser_initializer_clause (parser, &non_constant_p); + } + if (BRACE_ENCLOSED_INITIALIZER_P (initializer)) + maybe_warn_cpp0x ("extended initializer lists"); + if (!non_constant_p) initializer = fold_non_dependent_expr (initializer); @@ -7202,7 +7255,7 @@ cp_parser_condition (cp_parser* parser) cp_finish_decl (decl, initializer, !non_constant_p, asm_specification, - LOOKUP_ONLYCONVERTING); + flags); if (pushed_scope) pop_scope (pushed_scope); @@ -7426,6 +7479,7 @@ cp_parser_for_init_statement (cp_parser* parser) break ; continue ; return expression [opt] ; + return braced-init-list ; goto identifier ; GNU extension: @@ -7496,12 +7550,18 @@ cp_parser_jump_statement (cp_parser* parser) case RID_RETURN: { tree expr; + bool expr_non_constant_p; - /* If the next token is a `;', then there is no - expression. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + maybe_warn_cpp0x ("extended initializer lists"); + expr = cp_parser_braced_list (parser, &expr_non_constant_p); + } + else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) expr = cp_parser_expression (parser, /*cast_p=*/false); else + /* If the next token is a `;', then there is no + expression. */ expr = NULL_TREE; /* Build the return-statement. */ statement = finish_return_stmt (expr); @@ -7964,7 +8024,8 @@ cp_parser_simple_declaration (cp_parser* parser, is not a parenthesis, then we must be looking at a declaration. (After "int (" we might be looking at a functional cast.) */ if (decl_specifiers.any_specifiers_p - && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) + && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN) + && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) cp_parser_commit_to_tentative_parse (parser); /* Keep going until we hit the `;' at the end of the simple @@ -8907,6 +8968,7 @@ cp_parser_mem_initializer_list (cp_parser* parser) mem-initializer: mem-initializer-id ( expression-list [opt] ) + mem-initializer-id braced-init-list GNU extension: @@ -8937,11 +8999,20 @@ cp_parser_mem_initializer (cp_parser* parser) if (member && !DECL_P (member)) in_base_initializer = 1; - expression_list - = cp_parser_parenthesized_expression_list (parser, false, - /*cast_p=*/false, - /*allow_expansion_p=*/true, - /*non_constant_p=*/NULL); + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + bool expr_non_constant_p; + maybe_warn_cpp0x ("extended initializer lists"); + expression_list = cp_parser_braced_list (parser, &expr_non_constant_p); + CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; + expression_list = build_tree_list (NULL_TREE, expression_list); + } + else + expression_list + = cp_parser_parenthesized_expression_list (parser, false, + /*cast_p=*/false, + /*allow_expansion_p=*/true, + /*non_constant_p=*/NULL); if (expression_list == error_mark_node) return error_mark_node; if (!expression_list) @@ -12197,7 +12268,7 @@ cp_parser_init_declarator (cp_parser* parser, initialized with "= ..", CPP_OPEN_PAREN if initialized with "(...)". */ enum cpp_ttype initialization_kind; - bool is_parenthesized_init = false; + bool is_direct_init = false; bool is_non_constant_init; int ctor_dtor_or_conv_p; bool friend_p; @@ -12263,7 +12334,8 @@ cp_parser_init_declarator (cp_parser* parser, token = cp_lexer_peek_token (parser->lexer); /* Check to see if the token indicates the start of a function-definition. */ - if (cp_parser_token_starts_function_definition_p (token)) + if (function_declarator_p (declarator) + && cp_parser_token_starts_function_definition_p (token)) { if (!function_definition_allowed_p) { @@ -12314,9 +12386,10 @@ cp_parser_init_declarator (cp_parser* parser, return error_mark_node; } - /* An `=' or an `(' indicates an initializer. */ + /* An `=' or an `(', or an '{' in C++0x, indicates an initializer. */ if (token->type == CPP_EQ - || token->type == CPP_OPEN_PAREN) + || token->type == CPP_OPEN_PAREN + || token->type == CPP_OPEN_BRACE) { is_initialized = true; initialization_kind = token->type; @@ -12399,7 +12472,7 @@ cp_parser_init_declarator (cp_parser* parser, /* Parse the initializer. */ initializer = NULL_TREE; - is_parenthesized_init = false; + is_direct_init = false; is_non_constant_init = true; if (is_initialized) { @@ -12422,7 +12495,7 @@ cp_parser_init_declarator (cp_parser* parser, } else initializer = cp_parser_initializer (parser, - &is_parenthesized_init, + &is_direct_init, &is_non_constant_init); } @@ -12430,7 +12503,8 @@ cp_parser_init_declarator (cp_parser* parser, initializer. Mark Mitchell proposed removing this functionality on the GCC mailing lists on 2002-08-13. This parser accepts the attributes -- but ignores them. */ - if (cp_parser_allow_gnu_extensions_p (parser) && is_parenthesized_init) + if (cp_parser_allow_gnu_extensions_p (parser) + && initialization_kind == CPP_OPEN_PAREN) if (cp_parser_attributes_opt (parser)) warning (OPT_Wattributes, "attributes after parenthesized initializer ignored"); @@ -12463,8 +12537,8 @@ cp_parser_init_declarator (cp_parser* parser, a direct-initialization, which means that an `explicit' constructor is OK. Otherwise, an `explicit' constructor cannot be used. */ - ((is_parenthesized_init || !is_initialized) - ? 0 : LOOKUP_ONLYCONVERTING)); + ((is_direct_init || !is_initialized) + ? 0 : LOOKUP_ONLYCONVERTING)); } else if ((cxx_dialect != cxx98) && friend_p && decl && TREE_CODE (decl) == FUNCTION_DECL) @@ -13983,14 +14057,14 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser) Returns an expression representing the initializer. If no initializer is present, NULL_TREE is returned. - *IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )' - production is used, and zero otherwise. *IS_PARENTHESIZED_INIT is - set to FALSE if there is no initializer present. If there is an + *IS_DIRECT_INIT is set to FALSE if the `= initializer-clause' + production is used, and TRUE otherwise. *IS_DIRECT_INIT is + set to TRUE if there is no initializer present. If there is an initializer, and it is not a constant-expression, *NON_CONSTANT_P is set to true; otherwise it is set to false. */ static tree -cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init, +cp_parser_initializer (cp_parser* parser, bool* is_direct_init, bool* non_constant_p) { cp_token *token; @@ -14001,7 +14075,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init, /* Let our caller know whether or not this initializer was parenthesized. */ - *is_parenthesized_init = (token->type == CPP_OPEN_PAREN); + *is_direct_init = (token->type != CPP_EQ); /* Assume that the initializer is constant. */ *non_constant_p = false; @@ -14017,6 +14091,12 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init, /*cast_p=*/false, /*allow_expansion_p=*/true, non_constant_p); + else if (token->type == CPP_OPEN_BRACE) + { + maybe_warn_cpp0x ("extended initializer lists"); + init = cp_parser_braced_list (parser, non_constant_p); + CONSTRUCTOR_IS_DIRECT_INIT (init) = 1; + } else { /* Anything else is an error. */ @@ -14031,20 +14111,14 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init, initializer-clause: assignment-expression - { initializer-list , [opt] } - { } + braced-init-list Returns an expression representing the initializer. If the `assignment-expression' production is used the value returned is simply a representation for the expression. - Otherwise, a CONSTRUCTOR is returned. The CONSTRUCTOR_ELTS will be - the elements of the initializer-list (or NULL, if the last - production is used). The TREE_TYPE for the CONSTRUCTOR will be - NULL_TREE. There is no way to detect whether or not the optional - trailing `,' was provided. NON_CONSTANT_P is as for - cp_parser_initializer. */ + Otherwise, calls cp_parser_braced_list. */ static tree cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) @@ -14066,25 +14140,46 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) initializer = fold_non_dependent_expr (initializer); } else + initializer = cp_parser_braced_list (parser, non_constant_p); + + return initializer; +} + +/* Parse a brace-enclosed initializer list. + + braced-init-list: + { initializer-list , [opt] } + { } + + Returns a CONSTRUCTOR. The CONSTRUCTOR_ELTS will be + the elements of the initializer-list (or NULL, if the last + production is used). The TREE_TYPE for the CONSTRUCTOR will be + NULL_TREE. There is no way to detect whether or not the optional + trailing `,' was provided. NON_CONSTANT_P is as for + cp_parser_initializer. */ + +static tree +cp_parser_braced_list (cp_parser* parser, bool* non_constant_p) +{ + tree initializer; + + /* Consume the `{' token. */ + cp_lexer_consume_token (parser->lexer); + /* Create a CONSTRUCTOR to represent the braced-initializer. */ + initializer = make_node (CONSTRUCTOR); + /* If it's not a `}', then there is a non-trivial initializer. */ + if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE)) { - /* Consume the `{' token. */ - cp_lexer_consume_token (parser->lexer); - /* Create a CONSTRUCTOR to represent the braced-initializer. */ - initializer = make_node (CONSTRUCTOR); - /* If it's not a `}', then there is a non-trivial initializer. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE)) - { - /* Parse the initializer list. */ - CONSTRUCTOR_ELTS (initializer) - = cp_parser_initializer_list (parser, non_constant_p); - /* A trailing `,' token is allowed. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) - cp_lexer_consume_token (parser->lexer); - } - /* Now, there should be a trailing `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); + /* Parse the initializer list. */ + CONSTRUCTOR_ELTS (initializer) + = cp_parser_initializer_list (parser, non_constant_p); + /* A trailing `,' token is allowed. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); } - + /* Now, there should be a trailing `}'. */ + cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>"); + TREE_TYPE (initializer) = init_list_type_node; return initializer; } @@ -17297,11 +17392,22 @@ cp_parser_functional_cast (cp_parser* parser, tree type) { tree expression_list; tree cast; + bool nonconst_p; + + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + maybe_warn_cpp0x ("extended initializer lists"); + expression_list = cp_parser_braced_list (parser, &nonconst_p); + CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; + if (TREE_CODE (type) == TYPE_DECL) + type = TREE_TYPE (type); + return finish_compound_literal (type, expression_list); + } expression_list = cp_parser_parenthesized_expression_list (parser, false, /*cast_p=*/true, - /*allow_expansion_p=*/true, + /*allow_expansion_p=*/true, /*non_constant_p=*/NULL); cast = build_functional_cast (type, expression_list, @@ -17352,6 +17458,22 @@ cp_parser_save_member_function_body (cp_parser* parser, /* Save away the tokens that make up the body of the function. */ first = parser->lexer->next_token; + /* We can have braced-init-list mem-initializers before the fn body. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) + { + cp_lexer_consume_token (parser->lexer); + while (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE) + && cp_lexer_next_token_is_not_keyword (parser->lexer, RID_TRY)) + { + /* cache_group will stop after an un-nested { } pair, too. */ + if (cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0)) + break; + + /* variadic mem-inits have ... after the ')'. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) + cp_lexer_consume_token (parser->lexer); + } + } cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0); /* Handle function try blocks. */ while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH)) @@ -18210,41 +18332,54 @@ cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser) parser->object_scope = NULL_TREE; } -/* Consume tokens up through a non-nested END token. */ +/* Consume tokens up through a non-nested END token. Returns TRUE if we + encounter the end of a block before what we were looking for. */ -static void +static bool cp_parser_cache_group (cp_parser *parser, enum cpp_ttype end, unsigned depth) { while (true) { - cp_token *token; + cp_token *token = cp_lexer_peek_token (parser->lexer); - /* Abort a parenthesized expression if we encounter a brace. */ + /* Abort a parenthesized expression if we encounter a semicolon. */ if ((end == CPP_CLOSE_PAREN || depth == 0) - && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) - return; + && token->type == CPP_SEMICOLON) + return true; /* If we've reached the end of the file, stop. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_EOF) + if (token->type == CPP_EOF || (end != CPP_PRAGMA_EOL - && cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL))) - return; - /* Consume the next token. */ - token = cp_lexer_consume_token (parser->lexer); + && token->type == CPP_PRAGMA_EOL)) + return true; + if (token->type == CPP_CLOSE_BRACE && depth == 0) + /* We've hit the end of an enclosing block, so there's been some + kind of syntax error. */ + return true; + + /* Consume the token. */ + cp_lexer_consume_token (parser->lexer); /* See if it starts a new group. */ if (token->type == CPP_OPEN_BRACE) { cp_parser_cache_group (parser, CPP_CLOSE_BRACE, depth + 1); + /* In theory this should probably check end == '}', but + cp_parser_save_member_function_body needs it to exit + after either '}' or ')' when called with ')'. */ if (depth == 0) - return; + return false; } else if (token->type == CPP_OPEN_PAREN) - cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1); + { + cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1); + if (depth == 0 && end == CPP_CLOSE_PAREN) + return false; + } else if (token->type == CPP_PRAGMA) cp_parser_cache_group (parser, CPP_PRAGMA_EOL, depth + 1); else if (token->type == end) - return; + return false; } } @@ -20503,10 +20638,10 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses) if (CLASS_TYPE_P (TREE_TYPE (decl)) || type_dependent_expression_p (decl)) { - bool is_parenthesized_init, is_non_constant_init; + bool is_direct_init, is_non_constant_init; init = cp_parser_initializer (parser, - &is_parenthesized_init, + &is_direct_init, &is_non_constant_init); cp_finish_decl (decl, init, !is_non_constant_init, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f24b6ff04b3..cce706f0705 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -11507,6 +11507,7 @@ tsubst_copy_and_build (tree t, bool process_index_p; int newlen; bool need_copy_p = false; + tree r; if (type == error_mark_node) return error_mark_node; @@ -11571,10 +11572,12 @@ tsubst_copy_and_build (tree t, } } + r = build_constructor (init_list_type_node, n); + if (TREE_HAS_CONSTRUCTOR (t)) - return finish_compound_literal (type, n); + return finish_compound_literal (type, r); - return build_constructor (NULL_TREE, n); + return r; } case TYPEID_EXPR: @@ -12271,6 +12274,8 @@ type_unification_real (tree tparms, arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg, arg_expr); + if (arg == init_list_type_node && arg_expr) + arg = arg_expr; if (unify (tparms, targs, parm, arg, arg_strict)) return 1; } @@ -13037,7 +13042,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) if (arg == error_mark_node) return 1; - if (arg == unknown_type_node) + if (arg == unknown_type_node + || arg == init_list_type_node) /* We can't deduce anything from this, but we might get all the template args from other function args. */ return 0; @@ -13049,6 +13055,31 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) if (arg == parm && !uses_template_parms (parm)) return 0; + /* Handle init lists early, so the rest of the function can assume + we're dealing with a type. */ + if (BRACE_ENCLOSED_INITIALIZER_P (arg)) + { + tree elt, elttype; + unsigned i; + + if (!is_std_init_list (parm)) + /* We can only deduce from an initializer list argument if the + parameter is std::initializer_list; otherwise this is a + non-deduced context. */ + return 0; + + elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0); + + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt) + { + if (!BRACE_ENCLOSED_INITIALIZER_P (elt)) + elt = TREE_TYPE (elt); + if (unify (tparms, targs, elttype, elt, UNIFY_ALLOW_NONE)) + return 1; + } + return 0; + } + /* Immediately reject some pairs that won't unify because of cv-qualification mismatches. */ if (TREE_CODE (arg) == TREE_CODE (parm) diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 1dcd785371a..8a36f0b77b7 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -900,7 +900,7 @@ tinfo_base_init (tinfo_s *ti, tree target) init = tree_cons (NULL_TREE, decay_conversion (name_decl), init); - init = build_constructor_from_list (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (init_list_type_node, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_STATIC (init) = 1; init = tree_cons (NULL_TREE, init, NULL_TREE); @@ -917,7 +917,7 @@ generic_initializer (tinfo_s *ti, tree target) { tree init = tinfo_base_init (ti, target); - init = build_constructor_from_list (NULL_TREE, init); + init = build_constructor_from_list (init_list_type_node, init); TREE_CONSTANT (init) = 1; TREE_STATIC (init) = 1; return init; @@ -942,7 +942,7 @@ ptr_initializer (tinfo_s *ti, tree target) get_tinfo_ptr (TYPE_MAIN_VARIANT (to)), init); - init = build_constructor_from_list (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (init_list_type_node, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_STATIC (init) = 1; return init; @@ -974,7 +974,7 @@ ptm_initializer (tinfo_s *ti, tree target) get_tinfo_ptr (klass), init); - init = build_constructor_from_list (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (init_list_type_node, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_STATIC (init) = 1; return init; @@ -990,7 +990,7 @@ class_initializer (tinfo_s *ti, tree target, tree trail) tree init = tinfo_base_init (ti, target); TREE_CHAIN (init) = trail; - init = build_constructor_from_list (NULL_TREE, init); + init = build_constructor_from_list (init_list_type_node, init); TREE_CONSTANT (init) = 1; TREE_STATIC (init) = 1; return init; @@ -1102,10 +1102,10 @@ get_pseudo_ti_init (tree type, unsigned tk_index) build_int_cst (offset_type, flags)); base_init = tree_cons (NULL_TREE, offset, base_init); base_init = tree_cons (NULL_TREE, tinfo, base_init); - base_init = build_constructor_from_list (NULL_TREE, base_init); + base_init = build_constructor_from_list (init_list_type_node, base_init); base_inits = tree_cons (NULL_TREE, base_init, base_inits); } - base_inits = build_constructor_from_list (NULL_TREE, base_inits); + base_inits = build_constructor_from_list (init_list_type_node, base_inits); base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE); /* Prepend the number of bases. */ base_inits = tree_cons (NULL_TREE, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 2400aeb37da..fa65e9b2804 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2099,21 +2099,17 @@ finish_unary_op_expr (enum tree_code code, tree expr) } /* Finish a compound-literal expression. TYPE is the type to which - the INITIALIZER_LIST is being cast. */ + the CONSTRUCTOR in COMPOUND_LITERAL is being cast. */ tree -finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list) +finish_compound_literal (tree type, tree compound_literal) { - tree compound_literal; - if (!TYPE_OBJ_P (type)) { error ("compound literal of non-object type %qT", type); return error_mark_node; } - /* Build a CONSTRUCTOR for the INITIALIZER_LIST. */ - compound_literal = build_constructor (NULL_TREE, initializer_list); if (processing_template_decl) { TREE_TYPE (compound_literal) = type; @@ -2123,6 +2119,18 @@ finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list) } type = complete_type (type); + + if (TYPE_NON_AGGREGATE_CLASS (type)) + { + /* Trying to deal with a CONSTRUCTOR instead of a TREE_LIST + everywhere that deals with function arguments would be a pain, so + just wrap it in a TREE_LIST. The parser set a flag so we know + that it came from T{} rather than T({}). */ + CONSTRUCTOR_IS_DIRECT_INIT (compound_literal) = 1; + compound_literal = build_tree_list (NULL_TREE, compound_literal); + return build_functional_cast (type, compound_literal, tf_error); + } + if (TREE_CODE (type) == ARRAY_TYPE && check_array_initializer (NULL_TREE, type, compound_literal)) return error_mark_node; @@ -2130,7 +2138,19 @@ finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list) if (TREE_CODE (type) == ARRAY_TYPE) cp_complete_array_type (&type, compound_literal, false); compound_literal = digest_init (type, compound_literal); - return get_target_expr (compound_literal); + if ((!at_function_scope_p () || cp_type_readonly (type)) + && initializer_constant_valid_p (compound_literal, type)) + { + tree decl = create_temporary_var (type); + DECL_INITIAL (decl) = compound_literal; + TREE_STATIC (decl) = 1; + decl = pushdecl_top_level (decl); + DECL_NAME (decl) = make_anon_name (); + SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl)); + return decl; + } + else + return get_target_expr (compound_literal); } /* Return the declaration for the function-name variable indicated by diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index ff372206ee6..b7c0a8d33b8 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -616,6 +616,14 @@ build_cplus_array_type (tree elt_type, tree index_type) return t; } +/* Return an ARRAY_TYPE with element type ELT and length N. */ + +tree +build_array_of_n_type (tree elt, int n) +{ + return build_cplus_array_type (elt, build_index_type (size_int (n - 1))); +} + /* Return a reference type node referring to TO_TYPE. If RVAL is true, return an rvalue reference type, otherwise return an lvalue reference type. If a type node exists, reuse it, otherwise create diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 14cbd9d8dd2..409f34068d4 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2887,13 +2887,6 @@ cp_build_function_call (tree function, tree params, tsubst_flags_t complain) if (nargs < 0) return error_mark_node; - /* Check that arguments to builtin functions match the expectations. */ - if (fndecl - && DECL_BUILT_IN (fndecl) - && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL - && !check_builtin_function_arguments (fndecl, nargs, argarray)) - return error_mark_node; - /* Check for errors in format strings and inappropriately null parameters. */ check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray, diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 05e88b9002e..4cf8021964f 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "output.h" #include "diagnostic.h" +#include "real.h" static tree process_init_constructor (tree type, tree init); @@ -592,7 +593,7 @@ store_init_value (tree decl, tree init) { error ("constructor syntax used, but no constructor declared " "for type %qT", type); - init = build_constructor_from_list (NULL_TREE, nreverse (init)); + init = build_constructor_from_list (init_list_type_node, nreverse (init)); } } else if (TREE_CODE (init) == TREE_LIST @@ -631,15 +632,70 @@ store_init_value (tree decl, tree init) } +/* Give errors about narrowing conversions within { }. */ + +void +check_narrowing (tree type, tree init) +{ + tree ftype = TREE_TYPE (init); + bool ok = true; + REAL_VALUE_TYPE d; + + if (DECL_P (init)) + init = decl_constant_value (init); + + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (ftype) == REAL_TYPE) + ok = false; + else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype) + && CP_INTEGRAL_TYPE_P (type)) + { + if (TYPE_PRECISION (type) < TYPE_PRECISION (ftype) + && (TREE_CODE (init) != INTEGER_CST + || !int_fits_type_p (init, type))) + ok = false; + } + else if (TREE_CODE (ftype) == REAL_TYPE + && TREE_CODE (type) == REAL_TYPE) + { + if (TYPE_PRECISION (type) < TYPE_PRECISION (ftype)) + { + ok = false; + if (TREE_CODE (init) == REAL_CST) + { + d = TREE_REAL_CST (init); + if (exact_real_truncate (TYPE_MODE (type), &d)) + ok = true; + } + } + } + else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype) + && TREE_CODE (type) == REAL_TYPE) + { + ok = false; + if (TREE_CODE (init) == INTEGER_CST) + { + d = real_value_from_int_cst (0, init); + if (exact_real_truncate (TYPE_MODE (type), &d)) + ok = true; + } + } + + if (!ok) + error ("narrowing conversion of %qE to %qT inside { }", init, type); +} + /* Process the initializer INIT for a variable of type TYPE, emitting diagnostics for invalid initializers and converting the initializer as appropriate. For aggregate types, it assumes that reshape_init has already run, thus the - initializer will have the right shape (brace elision has been undone). */ + initializer will have the right shape (brace elision has been undone). -tree -digest_init (tree type, tree init) + NESTED is true iff we are being called for an element of a CONSTRUCTOR. */ + +static tree +digest_init_r (tree type, tree init, bool nested) { enum tree_code code = TREE_CODE (type); @@ -706,6 +762,8 @@ digest_init (tree type, tree init) { tree *exp; + if (cxx_dialect != cxx98 && nested) + check_narrowing (type, init); init = convert_for_initialization (0, type, init, LOOKUP_NORMAL, "initialization", NULL_TREE, 0, tf_warning_or_error); @@ -731,7 +789,7 @@ digest_init (tree type, tree init) || TREE_CODE (type) == COMPLEX_TYPE); if (BRACE_ENCLOSED_INITIALIZER_P (init)) - return process_init_constructor (type, init); + return process_init_constructor (type, init); else { if (COMPOUND_LITERAL_P (init) && TREE_CODE (type) == ARRAY_TYPE) @@ -757,6 +815,11 @@ digest_init (tree type, tree init) } } +tree +digest_init (tree type, tree init) +{ + return digest_init_r (type, init, false); +} /* Set of flags used within process_init_constructor to describe the initializers. */ @@ -828,7 +891,7 @@ process_init_constructor_array (tree type, tree init) else ce->index = size_int (i); gcc_assert (ce->value); - ce->value = digest_init (TREE_TYPE (type), ce->value); + ce->value = digest_init_r (TREE_TYPE (type), ce->value, true); if (ce->value != error_mark_node) gcc_assert (same_type_ignoring_top_level_qualifiers_p @@ -854,7 +917,7 @@ process_init_constructor_array (tree type, tree init) next = build_functional_cast (TREE_TYPE (type), NULL_TREE, tf_warning_or_error); else - next = build_constructor (NULL_TREE, NULL); + next = build_constructor (init_list_type_node, NULL); next = digest_init (TREE_TYPE (type), next); } else if (!zero_init_p (TREE_TYPE (type))) @@ -929,7 +992,7 @@ process_init_constructor_record (tree type, tree init) } gcc_assert (ce->value); - next = digest_init (TREE_TYPE (field), ce->value); + next = digest_init_r (TREE_TYPE (field), ce->value, true); ++idx; } else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field))) @@ -942,9 +1005,9 @@ process_init_constructor_record (tree type, tree init) next = build_functional_cast (TREE_TYPE (field), NULL_TREE, tf_warning_or_error); else - next = build_constructor (NULL_TREE, NULL); + next = build_constructor (init_list_type_node, NULL); - next = digest_init (TREE_TYPE (field), next); + next = digest_init_r (TREE_TYPE (field), next, true); /* Warn when some struct elements are implicitly initialized. */ warning (OPT_Wmissing_field_initializers, @@ -1037,7 +1100,7 @@ process_init_constructor_union (tree type, tree init) } if (ce->value && ce->value != error_mark_node) - ce->value = digest_init (TREE_TYPE (ce->index), ce->value); + ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, true); return picflag_from_initializer (ce->value); } diff --git a/gcc/df-problems.c b/gcc/df-problems.c index 28c99638ec3..0c46bdaa496 100644 --- a/gcc/df-problems.c +++ b/gcc/df-problems.c @@ -3191,7 +3191,7 @@ df_set_note (enum reg_note note_type, rtx insn, rtx old, rtx reg) } /* Did not find the note. */ - REG_NOTES (insn) = alloc_EXPR_LIST (note_type, reg, REG_NOTES (insn)); + add_reg_note (insn, note_type, reg); return old; } diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 86c2f46a49e..8913ec0c923 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -3427,15 +3427,17 @@ applications. There are no standard Unix configurations. @end html @heading @anchor{m68k-x-x}m68k-*-* By default, @samp{m68k-*-aout}, @samp{m68k-*-coff*}, -@samp{m68k-*-elf*}, @samp{m68k-*-rtems} and @samp{m68k-*-uclinux} +@samp{m68k-*-elf*}, @samp{m68k-*-rtems}, @samp{m68k-*-uclinux} and +@samp{m68k-*-linux} build libraries for both M680x0 and ColdFire processors. If you only need the M680x0 libraries, you can omit the ColdFire ones by passing @option{--with-arch=m68k} to @command{configure}. Alternatively, you can omit the M680x0 libraries by passing @option{--with-arch=cf} to -@command{configure}. These targets default to 5206 code when +@command{configure}. These targets default to 5206 or 5475 code as +appropriate for the target system when configured with @option{--with-arch=cf} and 68020 code otherwise. -The @samp{m68k-*-linux-gnu}, @samp{m68k-*-netbsd} and +The @samp{m68k-*-netbsd} and @samp{m68k-*-openbsd} targets also support the @option{--with-arch} option. They will generate ColdFire CFV4e code when configured with @option{--with-arch=cf} and 68020 code otherwise. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ed73610a7dc..a87d89e9d84 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -310,7 +310,7 @@ Objective-C and Objective-C++ Dialects}. -p -pg -print-file-name=@var{library} -print-libgcc-file-name @gol -print-multi-directory -print-multi-lib @gol -print-prog-name=@var{program} -print-search-dirs -Q @gol --print-sysroot-headers-suffix @gol +-print-sysroot -print-sysroot-headers-suffix @gol -save-temps -time} @item Optimization Options @@ -5064,6 +5064,14 @@ variable @env{GCC_EXEC_PREFIX} to the directory where you installed them. Don't forget the trailing @samp{/}. @xref{Environment Variables}. +@item -print-sysroot +@opindex print-sysroot +Print the target sysroot directory that will be used during +compilation. This is the target sysroot specified either at configure +time or or using the @option{--sysroot} option, possibly with an extra +suffix that depends on compilation options. If no target sysroot is +specified, the option prints nothing. + @item -print-sysroot-headers-suffix @opindex print-sysroot-headers-suffix Print the suffix added to the target sysroot when searching for @@ -7328,7 +7336,8 @@ duplicated when threading jumps. @item max-fields-for-field-sensitive Maximum number of fields in a structure we will treat in -a field sensitive manner during pointer analysis. +a field sensitive manner during pointer analysis. The default is zero +for -O0, and -O1 and 100 for -Os, -O2, and -O3. @item prefetch-latency Estimate on average number of instructions that are executed before diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index d4ba0e20814..b5418a3f465 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4187,6 +4187,18 @@ This hook returns a type node for @code{va_list} for the target. The default version of the hook returns @code{void*}. @end deftypefn +@deftypefn {Target Hook} tree TARGET_FN_ABI_VA_LIST (tree @var{fndecl}) +This hook returns the va_list type of the calling convention specified by +@var{fndecl}. +The default version of this hook returns @code{va_list_type_node}. +@end deftypefn + +@deftypefn {Target Hook} tree TARGET_CANONICAL_VA_LIST_TYPE (tree @var{type}) +This hook returns the va_list type of the calling convention specified by the +type of @var{type}. If @var{type} is not a valid va_list type, it returns +@code{NULL_TREE}. +@end deftypefn + @deftypefn {Target Hook} tree TARGET_GIMPLIFY_VA_ARG_EXPR (tree @var{valist}, tree @var{type}, tree *@var{pre_p}, tree *@var{post_p}) This hook performs target-specific gimplification of @code{VA_ARG_EXPR}. The first two parameters correspond to the @@ -4317,6 +4329,20 @@ function use different registers for the return value, this macro should recognize only the caller's register numbers. @end defmac +@defmac TARGET_ENUM_VA_LIST (@var{idx}, @var{pname}, @var{ptype}) +This target macro is used in function @code{c_common_nodes_and_builtins} +to iterate through the target specific builtin types for va_list. The +variable @var{idx} is used as iterator. @var{pname} has to be a pointer +to a @code{const char *} and @var{ptype} a pointer to a @code{tree} typed +variable. +The arguments @var{pname} and @var{ptype} are used to store the result of +this macro and are set to the name of the va_list builtin type and its +internal type. +If the return value of this macro is zero, then there is no more element. +Otherwise the @var{IDX} should be increased for the next call of this +macro to iterate through all types. +@end defmac + @defmac APPLY_RESULT_SIZE Define this macro if @samp{untyped_call} and @samp{untyped_return} need more space than is implied by @code{FUNCTION_VALUE_REGNO_P} for diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 418da241b66..22c7979a773 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -3044,9 +3044,8 @@ link_cc0_insns (rtx insn) if (NONJUMP_INSN_P (user) && GET_CODE (PATTERN (user)) == SEQUENCE) user = XVECEXP (PATTERN (user), 0, 0); - REG_NOTES (user) = gen_rtx_INSN_LIST (REG_CC_SETTER, insn, - REG_NOTES (user)); - REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_CC_USER, user, REG_NOTES (insn)); + add_reg_note (user, REG_CC_SETTER, insn); + add_reg_note (insn, REG_CC_USER, user); } /* Return the next insn that uses CC0 after INSN, which is assumed to @@ -3223,10 +3222,7 @@ try_split (rtx pat, rtx trial, int last) is responsible for this step using split_branch_probability variable. */ gcc_assert (njumps == 1); - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_BR_PROB, - GEN_INT (probability), - REG_NOTES (insn)); + add_reg_note (insn, REG_BR_PROB, GEN_INT (probability)); } } } @@ -3257,10 +3253,7 @@ try_split (rtx pat, rtx trial, int last) if (CALL_P (insn) || (flag_non_call_exceptions && INSN_P (insn) && may_trap_p (PATTERN (insn)))) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_EH_REGION, - XEXP (note, 0), - REG_NOTES (insn)); + add_reg_note (insn, REG_EH_REGION, XEXP (note, 0)); } break; @@ -3269,10 +3262,7 @@ try_split (rtx pat, rtx trial, int last) for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn)) { if (CALL_P (insn)) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), - XEXP (note, 0), - REG_NOTES (insn)); + add_reg_note (insn, REG_NOTE_KIND (note), XEXP (note, 0)); } break; @@ -3280,10 +3270,7 @@ try_split (rtx pat, rtx trial, int last) for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn)) { if (JUMP_P (insn)) - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), - XEXP (note, 0), - REG_NOTES (insn)); + add_reg_note (insn, REG_NOTE_KIND (note), XEXP (note, 0)); } break; @@ -3294,8 +3281,7 @@ try_split (rtx pat, rtx trial, int last) rtx reg = XEXP (note, 0); if (!FIND_REG_INC_NOTE (insn, reg) && for_each_rtx (&PATTERN (insn), find_auto_inc, reg) > 0) - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, reg, - REG_NOTES (insn)); + add_reg_note (insn, REG_INC, reg); } break; #endif @@ -4600,7 +4586,6 @@ rtx set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum) { rtx note = find_reg_note (insn, kind, NULL_RTX); - rtx new_note = NULL; switch (kind) { @@ -4638,8 +4623,7 @@ set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum) break; } - new_note = gen_rtx_EXPR_LIST (kind, datum, REG_NOTES (insn)); - REG_NOTES (insn) = new_note; + add_reg_note (insn, kind, datum); switch (kind) { @@ -5525,13 +5509,10 @@ emit_copy_of_insn_after (rtx insn, rtx after) if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND) { if (GET_CODE (link) == EXPR_LIST) - REG_NOTES (new) - = gen_rtx_EXPR_LIST (REG_NOTE_KIND (link), - copy_insn_1 (XEXP (link, 0)), REG_NOTES (new)); + add_reg_note (new, REG_NOTE_KIND (link), + copy_insn_1 (XEXP (link, 0))); else - REG_NOTES (new) - = gen_rtx_INSN_LIST (REG_NOTE_KIND (link), - XEXP (link, 0), REG_NOTES (new)); + add_reg_note (new, REG_NOTE_KIND (link), XEXP (link, 0)); } INSN_CODE (new) = INSN_CODE (insn); diff --git a/gcc/expr.c b/gcc/expr.c index 6d6278a7bc7..33616d6900e 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -7102,10 +7102,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, && GET_CODE (PATTERN (insn)) != CLOBBER && GET_CODE (PATTERN (insn)) != USE && (CALL_P (insn) || may_trap_p (PATTERN (insn)))) - { - REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION, GEN_INT (rn), - REG_NOTES (insn)); - } + add_reg_note (insn, REG_EH_REGION, GEN_INT (rn)); } } diff --git a/gcc/expr.h b/gcc/expr.h index beb44bd80b7..39a51fcfe13 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -342,6 +342,9 @@ extern rtx emit_store_flag_force (rtx, enum rtx_code, rtx, rtx, /* Functions from builtins.c: */ extern rtx expand_builtin (tree, rtx, rtx, enum machine_mode, int); extern tree std_build_builtin_va_list (void); +extern tree std_fn_abi_va_list (tree); +extern tree std_canonical_va_list_type (tree); + extern void std_expand_builtin_va_start (tree, rtx); extern rtx default_expand_builtin (tree, rtx, rtx, enum machine_mode, int); extern void expand_builtin_setjmp_setup (rtx, rtx); diff --git a/gcc/fold-const.c b/gcc/fold-const.c index fc72b9b38a2..e1e04bb625d 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -2396,7 +2396,8 @@ fold_convert_const (enum tree_code code, tree type, tree arg1) if (TREE_TYPE (arg1) == type) return arg1; - if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type)) + if (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type) + || TREE_CODE (type) == OFFSET_TYPE) { if (TREE_CODE (arg1) == INTEGER_CST) return fold_convert_const_int_from_int (type, arg1); diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 82c2392d14d..44f61fa2458 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,39 @@ +2008-07-07 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/36670 + * iresolve.c (gfc_resolve_product): Set shape of return + value from array. + (gfc_resolve_sum): Likewise. + +2008-07-07 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/36726 + * f95-lang.c (poplevel): Don't ever add subblocks to + global_binding_level. + +2008-07-02 Janus Weil <janus@gcc.gnu.org> + Tobias Burnus <burnus@net-b.de> + Paul Thomas <pault@gcc.gnu.org> + + PR fortran/32580 + * gfortran.h (struct gfc_symbol): New member "proc_pointer". + * check.c (gfc_check_associated,gfc_check_null): Implement + procedure pointers. + * decl.c (match_procedure_decl): Ditto. + * expr.c (gfc_check_pointer_assign,gfc_check_assign_symbol): Ditto. + * interface.c (compare_actual_formal): Ditto. + * match.h: Ditto. + * match.c (gfc_match_pointer_assignment): Ditto. + * parse.c (parse_interface): Ditto. + * primary.c (gfc_match_rvalue,match_variable): Ditto. + * resolve.c (resolve_fl_procedure): Ditto. + * symbol.c (check_conflict,gfc_add_external,gfc_add_pointer, + gfc_copy_attr,gen_fptr_param,build_formal_args): Ditto. + * trans-decl.c (get_proc_pointer_decl,gfc_get_extern_function_decl, + create_function_arglist): Ditto. + * trans-expr.c (gfc_conv_variable,gfc_conv_function_val, + gfc_conv_function_call,gfc_trans_pointer_assignment): Ditto. + 2008-07-02 Thomas Koenig <tkoenig@gcc.gnu.org> PR fortran/36590 diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c index 87d962e50a7..c0f9891bd98 100644 --- a/gcc/fortran/check.c +++ b/gcc/fortran/check.c @@ -584,7 +584,7 @@ gfc_check_x_yd (gfc_expr *x, gfc_expr *y) try gfc_check_associated (gfc_expr *pointer, gfc_expr *target) { - symbol_attribute attr; + symbol_attribute attr1, attr2; int i; try t; locus *where; @@ -592,15 +592,15 @@ gfc_check_associated (gfc_expr *pointer, gfc_expr *target) where = &pointer->where; if (pointer->expr_type == EXPR_VARIABLE) - attr = gfc_variable_attr (pointer, NULL); + attr1 = gfc_variable_attr (pointer, NULL); else if (pointer->expr_type == EXPR_FUNCTION) - attr = pointer->symtree->n.sym->attr; + attr1 = pointer->symtree->n.sym->attr; else if (pointer->expr_type == EXPR_NULL) goto null_arg; else gcc_assert (0); /* Pointer must be a variable or a function. */ - if (!attr.pointer) + if (!attr1.pointer && !attr1.proc_pointer) { gfc_error ("'%s' argument of '%s' intrinsic at %L must be a POINTER", gfc_current_intrinsic_arg[0], gfc_current_intrinsic, @@ -617,9 +617,9 @@ gfc_check_associated (gfc_expr *pointer, gfc_expr *target) goto null_arg; if (target->expr_type == EXPR_VARIABLE) - attr = gfc_variable_attr (target, NULL); + attr2 = gfc_variable_attr (target, NULL); else if (target->expr_type == EXPR_FUNCTION) - attr = target->symtree->n.sym->attr; + attr2 = target->symtree->n.sym->attr; else { gfc_error ("'%s' argument of '%s' intrinsic at %L must be a pointer " @@ -628,7 +628,7 @@ gfc_check_associated (gfc_expr *pointer, gfc_expr *target) return FAILURE; } - if (!attr.pointer && !attr.target) + if (attr1.pointer && !attr2.pointer && !attr2.target) { gfc_error ("'%s' argument of '%s' intrinsic at %L must be a POINTER " "or a TARGET", gfc_current_intrinsic_arg[1], @@ -2071,7 +2071,7 @@ gfc_check_null (gfc_expr *mold) attr = gfc_variable_attr (mold, NULL); - if (!attr.pointer) + if (!attr.pointer && !attr.proc_pointer) { gfc_error ("'%s' argument of '%s' intrinsic at %L must be a POINTER", gfc_current_intrinsic_arg[0], diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 869ece6c3f6..d23a32946ef 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -4065,6 +4065,7 @@ match_procedure_decl (void) locus old_loc, entry_loc; gfc_symbol *sym, *proc_if = NULL; int num; + gfc_expr *initializer = NULL; old_loc = entry_loc = gfc_current_locus; @@ -4183,7 +4184,7 @@ got_ts: return MATCH_ERROR; } - if (!sym->attr.pointer && gfc_add_external (&sym->attr, NULL) == FAILURE) + if (gfc_add_external (&sym->attr, NULL) == FAILURE) return MATCH_ERROR; if (gfc_add_proc (&sym->attr, sym->name, NULL) == FAILURE) return MATCH_ERROR; @@ -4203,6 +4204,40 @@ got_ts: sym->attr.function = sym->ts.interface->attr.function; } + if (gfc_match (" =>") == MATCH_YES) + { + if (!current_attr.pointer) + { + gfc_error ("Initialization at %C isn't for a pointer variable"); + m = MATCH_ERROR; + goto cleanup; + } + + m = gfc_match_null (&initializer); + if (m == MATCH_NO) + { + gfc_error ("Pointer initialization requires a NULL() at %C"); + m = MATCH_ERROR; + } + + if (gfc_pure (NULL)) + { + gfc_error ("Initialization of pointer at %C is not allowed in " + "a PURE procedure"); + m = MATCH_ERROR; + } + + if (m != MATCH_YES) + goto cleanup; + + if (add_init_expr_to_sym (sym->name, &initializer, &gfc_current_locus) + != SUCCESS) + goto cleanup; + + } + + gfc_set_sym_referenced (sym); + if (gfc_match_eos () == MATCH_YES) return MATCH_YES; if (gfc_match_char (',') != MATCH_YES) @@ -4212,6 +4247,11 @@ got_ts: syntax: gfc_error ("Syntax error in PROCEDURE statement at %C"); return MATCH_ERROR; + +cleanup: + /* Free stuff up and return. */ + gfc_free_expr (initializer); + return m; } diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 2f7030ed833..12987e6b748 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -2874,7 +2874,8 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue) int is_pure; int pointer, check_intent_in; - if (lvalue->symtree->n.sym->ts.type == BT_UNKNOWN) + if (lvalue->symtree->n.sym->ts.type == BT_UNKNOWN + && !lvalue->symtree->n.sym->attr.proc_pointer) { gfc_error ("Pointer assignment target is not a POINTER at %L", &lvalue->where); @@ -2894,7 +2895,8 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue) /* Check INTENT(IN), unless the object itself is the component or sub-component of a pointer. */ check_intent_in = 1; - pointer = lvalue->symtree->n.sym->attr.pointer; + pointer = lvalue->symtree->n.sym->attr.pointer + | lvalue->symtree->n.sym->attr.proc_pointer; for (ref = lvalue->ref; ref; ref = ref->next) { @@ -2933,6 +2935,10 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue) if (rvalue->expr_type == EXPR_NULL && rvalue->ts.type == BT_UNKNOWN) return SUCCESS; + /* TODO checks on rvalue for a procedure pointer assignment. */ + if (lvalue->symtree->n.sym->attr.proc_pointer) + return SUCCESS; + if (!gfc_compare_types (&lvalue->ts, &rvalue->ts)) { gfc_error ("Different types in pointer assignment at %L; attempted " @@ -3024,7 +3030,7 @@ gfc_check_assign_symbol (gfc_symbol *sym, gfc_expr *rvalue) lvalue.symtree->n.sym = sym; lvalue.where = sym->declared_at; - if (sym->attr.pointer) + if (sym->attr.pointer || sym->attr.proc_pointer) r = gfc_check_pointer_assign (&lvalue, rvalue); else r = gfc_check_assign (&lvalue, rvalue, 1); diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index 794cc41a2d0..9dfb4233210 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -435,6 +435,10 @@ poplevel (int keep, int reverse, int functionbody) DECL_INITIAL (current_function_decl) = block_node; BLOCK_VARS (block_node) = 0; } + else if (current_binding_level == global_binding_level) + /* When using gfc_start_block/gfc_finish_block from middle-end hooks, + don't add newly created BLOCKs as sublocks of global_binding_level. */ + ; else if (block_node) { current_binding_level->blocks diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 5d025db869b..aa2296c72a5 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -620,7 +620,7 @@ typedef struct unsigned allocatable:1, dimension:1, external:1, intrinsic:1, optional:1, pointer:1, target:1, value:1, volatile_:1, dummy:1, result:1, assign:1, threadprivate:1, not_always_present:1, - implied_index:1, subref_array_pointer:1; + implied_index:1, subref_array_pointer:1, proc_pointer:1; ENUM_BITFIELD (save_state) save:2; diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c index 26b4591166a..a20319976bb 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -1959,6 +1959,17 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal, return 0; } + /* Satisfy 12.4.1.3 by ensuring that a procedure pointer actual argument + is provided for a procedure pointer formal argument. */ + if (f->sym->attr.proc_pointer + && !a->expr->symtree->n.sym->attr.proc_pointer) + { + if (where) + gfc_error ("Expected a procedure pointer for argument '%s' at %L", + f->sym->name, &a->expr->where); + return 0; + } + /* Satisfy 12.4.1.2 by ensuring that a procedure actual argument is provided for a procedure formal argument. */ if (a->expr->ts.type != BT_PROCEDURE diff --git a/gcc/fortran/iresolve.c b/gcc/fortran/iresolve.c index 64a24e80007..2c804143ba9 100644 --- a/gcc/fortran/iresolve.c +++ b/gcc/fortran/iresolve.c @@ -1788,6 +1788,7 @@ gfc_resolve_product (gfc_expr *f, gfc_expr *array, gfc_expr *dim, if (dim != NULL) { f->rank = array->rank - 1; + f->shape = gfc_copy_shape_excluding (array->shape, array->rank, dim); gfc_resolve_dim_arg (dim); } @@ -2271,6 +2272,7 @@ gfc_resolve_sum (gfc_expr *f, gfc_expr *array, gfc_expr *dim, gfc_expr *mask) if (dim != NULL) { f->rank = array->rank - 1; + f->shape = gfc_copy_shape_excluding (array->shape, array->rank, dim); gfc_resolve_dim_arg (dim); } diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c index 6f5765f1784..d501d682475 100644 --- a/gcc/fortran/match.c +++ b/gcc/fortran/match.c @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #include "match.h" #include "parse.h" +int gfc_matching_procptr_assignment = 0; /* For debugging and diagnostic purposes. Return the textual representation of the intrinsic operator OP. */ @@ -1329,6 +1330,7 @@ gfc_match_pointer_assignment (void) old_loc = gfc_current_locus; lvalue = rvalue = NULL; + gfc_matching_procptr_assignment = 0; m = gfc_match (" %v =>", &lvalue); if (m != MATCH_YES) @@ -1337,7 +1339,11 @@ gfc_match_pointer_assignment (void) goto cleanup; } + if (lvalue->symtree->n.sym->attr.proc_pointer) + gfc_matching_procptr_assignment = 1; + m = gfc_match (" %e%t", &rvalue); + gfc_matching_procptr_assignment = 0; if (m != MATCH_YES) goto cleanup; diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h index cf30b2730dc..21a24795664 100644 --- a/gcc/fortran/match.h +++ b/gcc/fortran/match.h @@ -33,6 +33,8 @@ extern gfc_symbol *gfc_new_block; separate. */ extern gfc_st_label *gfc_statement_label; +extern int gfc_matching_procptr_assignment; + /****************** All gfc_match* routines *****************/ /* match.c. */ diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index c35db2d9cf6..781efbc205d 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -1992,6 +1992,11 @@ loop: new_state = COMP_SUBROUTINE; else if (st == ST_FUNCTION) new_state = COMP_FUNCTION; + if (gfc_new_block->attr.pointer) + { + gfc_new_block->attr.pointer = 0; + gfc_new_block->attr.proc_pointer = 1; + } if (gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY, gfc_new_block->formal, NULL) == FAILURE) { diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c index d7236e1be01..c67f2bd1873 100644 --- a/gcc/fortran/primary.c +++ b/gcc/fortran/primary.c @@ -2323,6 +2323,9 @@ gfc_match_rvalue (gfc_expr **result) } } + if (gfc_matching_procptr_assignment) + goto procptr0; + if (sym->attr.function || sym->attr.external || sym->attr.intrinsic) goto function0; @@ -2399,6 +2402,27 @@ gfc_match_rvalue (gfc_expr **result) /* If we're here, then the name is known to be the name of a procedure, yet it is not sure to be the name of a function. */ case FL_PROCEDURE: + + /* Procedure Pointer Assignments. */ + procptr0: + if (gfc_matching_procptr_assignment) + { + gfc_gobble_whitespace (); + if (sym->attr.function && gfc_peek_ascii_char () == '(') + /* Parse functions returning a procptr. */ + goto function0; + + if (sym->attr.flavor == FL_UNKNOWN) sym->attr.flavor = FL_PROCEDURE; + if (gfc_intrinsic_name (sym->name, 0) + || gfc_intrinsic_name (sym->name, 1)) + sym->attr.intrinsic = 1; + e = gfc_get_expr (); + e->expr_type = EXPR_VARIABLE; + e->symtree = symtree; + m = match_varspec (e, 0); + break; + } + if (sym->attr.subroutine) { gfc_error ("Unexpected use of subroutine name '%s' at %C", @@ -2780,6 +2804,9 @@ match_variable (gfc_expr **result, int equiv_flag, int host_flag) break; } + if (sym->attr.proc_pointer) + break; + /* Fall through to error */ default: diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 3b798d8643c..c0ec7847747 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -7330,7 +7330,8 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag) } } - if (sym->attr.function && sym->value && sym->attr.proc != PROC_ST_FUNCTION) + if (sym->attr.function && sym->value && sym->attr.proc != PROC_ST_FUNCTION + && !sym->attr.proc_pointer) { gfc_error ("Function '%s' at %L cannot have an initializer", sym->name, &sym->declared_at); @@ -7338,8 +7339,8 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag) } /* An external symbol may not have an initializer because it is taken to be - a procedure. */ - if (sym->attr.external && sym->value) + a procedure. Exception: Procedure Pointers. */ + if (sym->attr.external && sym->value && !sym->attr.proc_pointer) { gfc_error ("External object '%s' at %L may not have an initializer", sym->name, &sym->declared_at); diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index cd181d4f0f1..f91ef9157c0 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -410,13 +410,19 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where) case FL_BLOCK_DATA: case FL_MODULE: case FL_LABEL: - case FL_PROCEDURE: case FL_DERIVED: case FL_PARAMETER: a1 = gfc_code2string (flavors, attr->flavor); a2 = save; goto conflict; + case FL_PROCEDURE: + if (attr->proc_pointer) + break; + a1 = gfc_code2string (flavors, attr->flavor); + a2 = save; + goto conflict; + case FL_VARIABLE: case FL_NAMELIST: default: @@ -557,13 +563,6 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where) conf (procedure, value) conf (procedure, volatile_) conf (procedure, entry) - /* TODO: Implement procedure pointers. */ - if (attr->procedure && attr->pointer) - { - gfc_error ("Fortran 2003: Procedure pointers at %L are " - "not yet implemented in gfortran", where); - return FAILURE; - } a1 = gfc_code2string (flavors, attr->flavor); @@ -619,11 +618,11 @@ check_conflict (symbol_attribute *attr, const char *name, locus *where) break; case FL_PROCEDURE: - conf2 (intent); + if (!attr->proc_pointer) + conf2 (intent); if (attr->subroutine) { - conf2 (pointer); conf2 (target); conf2 (allocatable); conf2 (result); @@ -866,6 +865,12 @@ gfc_add_external (symbol_attribute *attr, locus *where) return FAILURE; } + if (attr->pointer && attr->if_source != IFSRC_IFBODY) + { + attr->pointer = 0; + attr->proc_pointer = 1; + } + attr->external = 1; return check_conflict (attr, NULL, where); @@ -916,7 +921,20 @@ gfc_add_pointer (symbol_attribute *attr, locus *where) if (check_used (attr, NULL, where)) return FAILURE; - attr->pointer = 1; + if (attr->pointer && !(attr->if_source == IFSRC_IFBODY + && gfc_find_state (COMP_INTERFACE) == FAILURE)) + { + duplicate_attr ("POINTER", where); + return FAILURE; + } + + if (attr->procedure || (attr->external && attr->if_source != IFSRC_IFBODY) + || (attr->if_source == IFSRC_IFBODY + && gfc_find_state (COMP_INTERFACE) == FAILURE)) + attr->proc_pointer = 1; + else + attr->pointer = 1; + return check_conflict (attr, NULL, where); } @@ -1641,6 +1659,8 @@ gfc_copy_attr (symbol_attribute *dest, symbol_attribute *src, locus *where) goto fail; if (src->intrinsic && gfc_add_intrinsic (dest, where) == FAILURE) goto fail; + if (src->proc_pointer) + dest->proc_pointer = 1; return SUCCESS; @@ -3574,7 +3594,7 @@ static void gen_fptr_param (gfc_formal_arglist **head, gfc_formal_arglist **tail, const char *module_name, - gfc_namespace *ns, const char *f_ptr_name) + gfc_namespace *ns, const char *f_ptr_name, int proc) { gfc_symbol *param_sym = NULL; gfc_symtree *param_symtree = NULL; @@ -3593,7 +3613,10 @@ gen_fptr_param (gfc_formal_arglist **head, /* Set up the necessary fields for the fptr output param sym. */ param_sym->refs++; - param_sym->attr.pointer = 1; + if (proc) + param_sym->attr.proc_pointer = 1; + else + param_sym->attr.pointer = 1; param_sym->attr.dummy = 1; param_sym->attr.use_assoc = 1; @@ -3773,21 +3796,23 @@ build_formal_args (gfc_symbol *new_proc_sym, gfc_current_ns->proc_name = new_proc_sym; /* Generate the params. */ - if ((old_sym->intmod_sym_id == ISOCBINDING_F_POINTER) || - (old_sym->intmod_sym_id == ISOCBINDING_F_PROCPOINTER)) + if (old_sym->intmod_sym_id == ISOCBINDING_F_PROCPOINTER) { gen_cptr_param (&head, &tail, (const char *) new_proc_sym->module, gfc_current_ns, "cptr", old_sym->intmod_sym_id); gen_fptr_param (&head, &tail, (const char *) new_proc_sym->module, - gfc_current_ns, "fptr"); - + gfc_current_ns, "fptr", 1); + } + else if (old_sym->intmod_sym_id == ISOCBINDING_F_POINTER) + { + gen_cptr_param (&head, &tail, (const char *) new_proc_sym->module, + gfc_current_ns, "cptr", old_sym->intmod_sym_id); + gen_fptr_param (&head, &tail, (const char *) new_proc_sym->module, + gfc_current_ns, "fptr", 0); /* If we're dealing with c_f_pointer, it has an optional third arg. */ - if (old_sym->intmod_sym_id == ISOCBINDING_F_POINTER) - { - gen_shape_param (&head, &tail, - (const char *) new_proc_sym->module, - gfc_current_ns, "shape"); - } + gen_shape_param (&head, &tail,(const char *) new_proc_sym->module, + gfc_current_ns, "shape"); + } else if (old_sym->intmod_sym_id == ISOCBINDING_ASSOCIATED) { diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 686e059ec4e..e960fa026b1 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -1104,6 +1104,44 @@ gfc_restore_sym (gfc_symbol * sym, gfc_saved_var * save) } +/* Declare a procedure pointer. */ + +static tree +get_proc_pointer_decl (gfc_symbol *sym) +{ + tree decl; + + decl = sym->backend_decl; + if (decl) + return decl; + + decl = build_decl (VAR_DECL, get_identifier (sym->name), + build_pointer_type (gfc_get_function_type (sym))); + + if (sym->ns->proc_name->backend_decl == current_function_decl + || sym->attr.contained) + gfc_add_decl_to_function (decl); + else + gfc_add_decl_to_parent_function (decl); + + sym->backend_decl = decl; + + if (!sym->attr.use_assoc + && (sym->attr.save != SAVE_NONE || sym->attr.data + || (sym->value && sym->ns->proc_name->attr.is_main_program))) + TREE_STATIC (decl) = 1; + + if (TREE_STATIC (decl) && sym->value) + { + /* Add static initializer. */ + DECL_INITIAL (decl) = gfc_conv_initializer (sym->value, &sym->ts, + TREE_TYPE (decl), sym->attr.dimension, sym->attr.proc_pointer); + } + + return decl; +} + + /* Get a basic decl for an external function. */ tree @@ -1126,6 +1164,9 @@ gfc_get_extern_function_decl (gfc_symbol * sym) to know that. */ gcc_assert (!(sym->attr.entry || sym->attr.entry_master)); + if (sym->attr.proc_pointer) + return get_proc_pointer_decl (sym); + if (sym->attr.intrinsic) { /* Call the resolution function to get the actual name. This is @@ -1540,6 +1581,9 @@ create_function_arglist (gfc_symbol * sym) type = gfc_sym_type (f->sym); } + if (f->sym->attr.proc_pointer) + type = build_pointer_type (type); + /* Build a the argument declaration. */ parm = build_decl (PARM_DECL, gfc_sym_identifier (f->sym), type); diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 59a0a2d8eb7..570e07b5a06 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -480,8 +480,7 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr) else if (sym->attr.flavor == FL_PROCEDURE && se->expr != current_function_decl) { - gcc_assert (se->want_pointer); - if (!sym->attr.dummy) + if (!sym->attr.dummy && !sym->attr.proc_pointer) { gcc_assert (TREE_CODE (se->expr) == FUNCTION_DECL); se->expr = build_fold_addr_expr (se->expr); @@ -1372,6 +1371,8 @@ gfc_conv_function_val (gfc_se * se, gfc_symbol * sym) if (sym->attr.dummy) { tmp = gfc_get_symbol_decl (sym); + if (sym->attr.proc_pointer) + tmp = build_fold_indirect_ref (tmp); gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE && TREE_CODE (TREE_TYPE (TREE_TYPE (tmp))) == FUNCTION_TYPE); } @@ -2498,9 +2499,10 @@ gfc_conv_function_call (gfc_se * se, gfc_symbol * sym, else { gfc_conv_expr_reference (&parmse, e); - if (fsym && fsym->attr.pointer - && fsym->attr.flavor != FL_PROCEDURE - && e->expr_type != EXPR_NULL) + if (fsym && e->expr_type != EXPR_NULL + && ((fsym->attr.pointer + && fsym->attr.flavor != FL_PROCEDURE) + || fsym->attr.proc_pointer)) { /* Scalar pointer dummy args require an extra level of indirection. The null pointer already contains @@ -3867,6 +3869,11 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) gfc_init_se (&rse, NULL); rse.want_pointer = 1; gfc_conv_expr (&rse, expr2); + + if (expr1->symtree->n.sym->attr.proc_pointer + && expr1->symtree->n.sym->attr.dummy) + lse.expr = build_fold_indirect_ref (lse.expr); + gfc_add_block_to_block (&block, &lse.pre); gfc_add_block_to_block (&block, &rse.pre); gfc_add_modify_expr (&block, lse.expr, diff --git a/gcc/function.c b/gcc/function.c index d8234da3877..69c2f68a4f9 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -2364,8 +2364,7 @@ assign_parm_remove_parallels (struct assign_parm_data_one *data) This can be done with register operations rather than on the stack, even if we will store the reconstituted parameter on the stack later. */ - if (GET_CODE (entry_parm) == PARALLEL - && data->passed_mode != BLKmode) + if (GET_CODE (entry_parm) == PARALLEL && GET_MODE (entry_parm) != BLKmode) { rtx parmreg = gen_reg_rtx (GET_MODE (entry_parm)); emit_group_store (parmreg, entry_parm, NULL_TREE, @@ -2421,6 +2420,8 @@ assign_parm_setup_block_p (struct assign_parm_data_one *data) { if (data->nominal_mode == BLKmode) return true; + if (GET_MODE (data->entry_parm) == BLKmode) + return true; #ifdef BLOCK_REG_PADDING /* Only assign_parm_setup_block knows how to deal with register arguments diff --git a/gcc/gcc.c b/gcc/gcc.c index 3da40a8c2a7..7914e4b6f35 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -155,6 +155,8 @@ static const char *print_prog_name = NULL; static int print_multi_directory; +static int print_sysroot; + /* Flag saying to print the relative path we'd use to find OS libraries given the current compiler flags. */ @@ -1162,6 +1164,7 @@ static const struct option_map option_map[] = {"--print-multi-directory", "-print-multi-directory", 0}, {"--print-multi-os-directory", "-print-multi-os-directory", 0}, {"--print-prog-name", "-print-prog-name=", "aj"}, + {"--print-sysroot", "-print-sysroot", 0}, {"--print-sysroot-headers-suffix", "-print-sysroot-headers-suffix", 0}, {"--profile", "-p", 0}, {"--profile-blocks", "-a", 0}, @@ -2973,7 +2976,7 @@ execute (void) for (argc = 0; commands[i].argv[argc] != NULL; argc++) ; - argv = alloca ((argc + 3) * sizeof (char *)); + argv = XALLOCAVEC (const char *, argc + 3); argv[0] = VALGRIND_PATH; argv[1] = "-q"; @@ -3244,6 +3247,7 @@ display_help (void) -print-multi-lib Display the mapping between command line options and\n\ multiple library search directories\n"), stdout); fputs (_(" -print-multi-os-directory Display the relative path to OS libraries\n"), stdout); + fputs (_(" -print-sysroot Display the target libraries directory\n"), stdout); fputs (_(" -print-sysroot-headers-suffix Display the sysroot suffix used to find headers\n"), stdout); fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler\n"), stdout); fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor\n"), stdout); @@ -3686,6 +3690,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" print_multi_lib = 1; else if (! strcmp (argv[i], "-print-multi-directory")) print_multi_directory = 1; + else if (! strcmp (argv[i], "-print-sysroot")) + print_sysroot = 1; else if (! strcmp (argv[i], "-print-multi-os-directory")) print_multi_os_directory = 1; else if (! strcmp (argv[i], "-print-sysroot-headers-suffix")) @@ -4126,6 +4132,8 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" ; else if (! strcmp (argv[i], "-print-multi-directory")) ; + else if (! strcmp (argv[i], "-print-sysroot")) + ; else if (! strcmp (argv[i], "-print-multi-os-directory")) ; else if (! strcmp (argv[i], "-print-sysroot-headers-suffix")) @@ -6529,6 +6537,18 @@ main (int argc, char **argv) return (0); } + if (print_sysroot) + { + if (target_system_root) + { + if (target_sysroot_suffix) + printf ("%s%s\n", target_system_root, target_sysroot_suffix); + else + printf ("%s\n", target_system_root); + } + return (0); + } + if (print_multi_os_directory) { if (multilib_os_dir == NULL) diff --git a/gcc/gcse.c b/gcc/gcse.c index 771df43a321..0955744855c 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -4562,9 +4562,8 @@ add_label_notes (rtx x, rtx insn) such a LABEL_REF, so we don't have to handle REG_LABEL_TARGET notes. */ gcc_assert (!JUMP_P (insn)); - REG_NOTES (insn) - = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, XEXP (x, 0), - REG_NOTES (insn)); + add_reg_note (insn, REG_LABEL_OPERAND, XEXP (x, 0)); + if (LABEL_P (XEXP (x, 0))) LABEL_NUSES (XEXP (x, 0))++; diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c index a01fa3f0b01..8c0e459fe38 100644 --- a/gcc/ggc-common.c +++ b/gcc/ggc-common.c @@ -638,7 +638,7 @@ mmap_gt_pch_get_address (size_t size, int fd) if (ret == (void *) MAP_FAILED) ret = NULL; else - munmap (ret, size); + munmap ((caddr_t) ret, size); return ret; } @@ -662,7 +662,7 @@ mmap_gt_pch_use_address (void *base, size_t size, int fd, size_t offset) if (size == 0) return -1; - addr = mmap (base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, + addr = mmap ((caddr_t) base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); return addr == base ? 1 : -1; @@ -791,7 +791,7 @@ static htab_t loc_hash; static hashval_t hash_descriptor (const void *p) { - const struct loc_descriptor *const d = p; + const struct loc_descriptor *const d = (const struct loc_descriptor *) p; return htab_hash_pointer (d->function) | d->line; } @@ -799,8 +799,8 @@ hash_descriptor (const void *p) static int eq_descriptor (const void *p1, const void *p2) { - const struct loc_descriptor *const d = p1; - const struct loc_descriptor *const d2 = p2; + const struct loc_descriptor *const d = (const struct loc_descriptor *) p1; + const struct loc_descriptor *const d2 = (const struct loc_descriptor *) p2; return (d->file == d2->file && d->line == d2->line && d->function == d2->function); @@ -819,7 +819,7 @@ struct ptr_hash_entry static hashval_t hash_ptr (const void *p) { - const struct ptr_hash_entry *const d = p; + const struct ptr_hash_entry *const d = (const struct ptr_hash_entry *) p; return htab_hash_pointer (d->ptr); } @@ -827,7 +827,7 @@ hash_ptr (const void *p) static int eq_ptr (const void *p1, const void *p2) { - const struct ptr_hash_entry *const p = p1; + const struct ptr_hash_entry *const p = (const struct ptr_hash_entry *) p1; return (p->ptr == p2); } @@ -848,7 +848,7 @@ loc_descriptor (const char *name, int line, const char *function) slot = (struct loc_descriptor **) htab_find_slot (loc_hash, &loc, 1); if (*slot) return *slot; - *slot = xcalloc (sizeof (**slot), 1); + *slot = XCNEW (struct loc_descriptor); (*slot)->file = name; (*slot)->line = line; (*slot)->function = function; @@ -883,7 +883,7 @@ ggc_record_overhead (size_t allocated, size_t overhead, void *ptr, static int ggc_prune_ptr (void **slot, void *b ATTRIBUTE_UNUSED) { - struct ptr_hash_entry *p = *slot; + struct ptr_hash_entry *p = (struct ptr_hash_entry *) *slot; if (!ggc_marked_p (p->ptr)) { p->loc->collected += p->size; @@ -907,7 +907,7 @@ ggc_free_overhead (void *ptr) { PTR *slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr), NO_INSERT); - struct ptr_hash_entry *p = *slot; + struct ptr_hash_entry *p = (struct ptr_hash_entry *) *slot; p->loc->freed += p->size; htab_clear_slot (ptr_hash, slot); free (p); @@ -917,8 +917,10 @@ ggc_free_overhead (void *ptr) static int final_cmp_statistic (const void *loc1, const void *loc2) { - struct loc_descriptor *l1 = *(struct loc_descriptor **) loc1; - struct loc_descriptor *l2 = *(struct loc_descriptor **) loc2; + const struct loc_descriptor *const l1 = + *(const struct loc_descriptor *const *) loc1; + const struct loc_descriptor *const l2 = + *(const struct loc_descriptor *const *) loc2; long diff; diff = ((long)(l1->allocated + l1->overhead - l1->freed) - (l2->allocated + l2->overhead - l2->freed)); @@ -929,8 +931,10 @@ final_cmp_statistic (const void *loc1, const void *loc2) static int cmp_statistic (const void *loc1, const void *loc2) { - struct loc_descriptor *l1 = *(struct loc_descriptor **) loc1; - struct loc_descriptor *l2 = *(struct loc_descriptor **) loc2; + const struct loc_descriptor *const l1 = + *(const struct loc_descriptor *const *) loc1; + const struct loc_descriptor *const l2 = + *(const struct loc_descriptor *const *) loc2; long diff; diff = ((long)(l1->allocated + l1->overhead - l1->freed - l1->collected) - @@ -967,7 +971,7 @@ dump_ggc_loc_statistics (bool final ATTRIBUTE_UNUSED) ggc_force_collect = true; ggc_collect (); - loc_array = xcalloc (sizeof (*loc_array), loc_hash->n_elements); + loc_array = XCNEWVEC (struct loc_descriptor *, loc_hash->n_elements); fprintf (stderr, "-------------------------------------------------------\n"); fprintf (stderr, "\n%-48s %10s %10s %10s %10s %10s\n", "source location", "Garbage", "Freed", "Leak", "Overhead", "Times"); diff --git a/gcc/ggc-zone.c b/gcc/ggc-zone.c index a80a6a0e979..5031a01b404 100644 --- a/gcc/ggc-zone.c +++ b/gcc/ggc-zone.c @@ -541,7 +541,7 @@ lookup_page_table_if_allocated (const void *p) return NULL; /* We might have a page entry which does not correspond exactly to a system page. */ - if (base[L1][L2] && (char *) p < base[L1][L2]->page) + if (base[L1][L2] && (const char *) p < base[L1][L2]->page) return NULL; return base[L1][L2]; @@ -566,7 +566,7 @@ set_page_table_entry (void *p, page_entry *entry) goto found; /* Not found -- allocate a new table. */ - table = xcalloc (1, sizeof(*table)); + table = XCNEW (struct page_table_chain); table->next = G.lookup; table->high_bits = high_bits; G.lookup = table; @@ -579,7 +579,7 @@ found: L2 = LOOKUP_L2 (p); if (base[L1] == NULL) - base[L1] = xcalloc (PAGE_L2_SIZE, sizeof (page_entry *)); + base[L1] = XCNEWVEC (page_entry *, PAGE_L2_SIZE); base[L1][L2] = entry; } @@ -715,7 +715,7 @@ zone_find_object_size (struct small_page_entry *page, unsigned int start_word = zone_get_object_alloc_word (object_midptr); unsigned int start_bit = zone_get_object_alloc_bit (object_midptr); size_t max_size = (page->common.page + SMALL_PAGE_SIZE - - (char *) object); + - (const char *) object); return zone_object_size_1 (page->alloc_bits, start_word, start_bit, max_size); @@ -898,7 +898,7 @@ alloc_small_page (struct alloc_zone *zone) memory order. */ for (i = G.quire_size - 1; i >= 1; i--) { - e = xcalloc (1, G.small_page_overhead); + e = XCNEWVAR (struct small_page_entry, G.small_page_overhead); e->common.page = page + (i << GGC_PAGE_SHIFT); e->common.zone = zone; e->next = f; @@ -908,7 +908,7 @@ alloc_small_page (struct alloc_zone *zone) zone->free_pages = f; - entry = xcalloc (1, G.small_page_overhead); + entry = XCNEWVAR (struct small_page_entry, G.small_page_overhead); entry->common.page = page; entry->common.zone = zone; set_page_table_entry (page, &entry->common); @@ -935,7 +935,7 @@ alloc_large_page (size_t size, struct alloc_zone *zone) size_t needed_size; needed_size = size + sizeof (struct large_page_entry); - page = xmalloc (needed_size); + page = XNEWVAR (char, needed_size); entry = (struct large_page_entry *) page; @@ -1439,7 +1439,7 @@ ggc_free (void *p) /* Add the chunk to the free list. We don't bother with coalescing, since we are likely to want a chunk of this size again. */ - free_chunk (p, size, page->zone); + free_chunk ((char *)p, size, page->zone); } } @@ -1494,7 +1494,7 @@ gt_ggc_m_S (const void *p) a STRING_CST. */ gcc_assert (offset == offsetof (struct tree_string, str)); p = ((const char *) p) - offset; - gt_ggc_mx_lang_tree_node ((void *) p); + gt_ggc_mx_lang_tree_node (CONST_CAST(void *, p)); return; } @@ -1560,7 +1560,7 @@ int ggc_marked_p (const void *p) { struct page_entry *page; - const char *ptr = p; + const char *ptr = (const char *) p; page = zone_get_object_page (p); @@ -1686,7 +1686,7 @@ init_ggc (void) if (GGC_PAGE_SIZE == G.pagesize) { /* We have a good page, might as well hold onto it... */ - e = xcalloc (1, G.small_page_overhead); + e = XCNEWVAR (struct small_page_entry, G.small_page_overhead); e->common.page = p; e->common.zone = &main_zone; e->next = main_zone.free_pages; @@ -1714,7 +1714,7 @@ new_ggc_zone_1 (struct alloc_zone *new_zone, const char * name) struct alloc_zone * new_ggc_zone (const char * name) { - struct alloc_zone *new_zone = xcalloc (1, sizeof (struct alloc_zone)); + struct alloc_zone *new_zone = XCNEW (struct alloc_zone); new_ggc_zone_1 (new_zone, name); return new_zone; } @@ -2301,7 +2301,7 @@ struct ggc_pch_data struct ggc_pch_data * init_ggc_pch (void) { - return xcalloc (sizeof (struct ggc_pch_data), 1); + return XCNEW (struct ggc_pch_data); } /* Return which of the page-aligned buckets the object at X, with type @@ -2380,7 +2380,7 @@ ggc_pch_this_base (struct ggc_pch_data *d, void *base_) } if (d->alloc_bits == NULL) - d->alloc_bits = xcalloc (1, d->alloc_size); + d->alloc_bits = XCNEWVAR (alloc_type, d->alloc_size); } /* Allocate a place for object X of size SIZE in the PCH file. */ @@ -2516,7 +2516,7 @@ ggc_pch_read (FILE *f, void *addr) /* Allocate the dummy page entry for the PCH, and set all pages mapped into the PCH to reference it. */ - pch_page = xcalloc (1, sizeof (struct page_entry)); + pch_page = XCNEW (struct page_entry); pch_page->page = pch_zone.page; pch_page->pch_p = true; diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 8d5b38bbf32..d614986b49c 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -3773,11 +3773,7 @@ create_check_block_twin (rtx insn, bool mutate_p) /* any_condjump_p (jump) == false. We don't need the same note for the check because any_condjump_p (check) == true. */ - { - REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_CROSSING_JUMP, - NULL_RTX, - REG_NOTES (jump)); - } + add_reg_note (jump, REG_CROSSING_JUMP, NULL_RTX); edge_flags = EDGE_CROSSING; } else diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 9e2153141d3..bda0fc261d6 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -153,7 +153,7 @@ static void ipcp_init_cloned_node (struct cgraph_node *orig_node, struct cgraph_node *new_node) { - ipa_create_node_params (new_node); + ipa_check_create_node_params (); IPA_NODE_REF (new_node)->ipcp_orig_node = orig_node; ipa_count_formal_params (new_node); ipa_create_param_decls_array (new_node); @@ -998,8 +998,9 @@ ipcp_driver (void) { if (dump_file) fprintf (dump_file, "\nIPA constant propagation start:\n"); - ipa_create_all_node_params (); - ipa_create_all_edge_args (); + ipa_check_create_node_params (); + ipa_check_create_edge_args (); + ipa_register_cgraph_hooks (); /* 1. Call the init stage to initialize the ipa_node_params and ipa_edge_args structures. */ ipcp_init_stage (); @@ -1025,8 +1026,7 @@ ipcp_driver (void) ipcp_print_profile_data (dump_file); } /* Free all IPCP structures. */ - ipa_free_all_node_params (); - ipa_free_all_edge_args (); + free_all_ipa_structures_after_ipa_cp (); if (dump_file) fprintf (dump_file, "\nIPA constant propagation end\n"); cgraph_remove_unreachable_nodes (true, NULL); diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index c5b4c9a80c8..f67d6579e10 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -28,8 +28,21 @@ along with GCC; see the file COPYING3. If not see #include "ipa-prop.h" #include "tree-flow.h" #include "tree-pass.h" +#include "tree-inline.h" #include "flags.h" #include "timevar.h" +#include "flags.h" + +/* Vector where the parameter infos are actually stored. */ +VEC (ipa_node_params_t, heap) *ipa_node_params_vector; +/* Vector where the parameter infos are actually stored. */ +VEC (ipa_edge_args_t, heap) *ipa_edge_args_vector; + +/* Holders of ipa cgraph hooks: */ +struct cgraph_edge_hook_list *edge_removal_hook_holder; +struct cgraph_node_hook_list *node_removal_hook_holder; +struct cgraph_2edge_hook_list *edge_duplication_hook_holder; +struct cgraph_2node_hook_list *node_duplication_hook_holder; /* Initialize worklist to contain all functions. */ struct ipa_func_list * @@ -176,7 +189,7 @@ ipa_detect_param_modifications (struct cgraph_node *mt) tree stmt, parm_tree; struct ipa_node_params *info = IPA_NODE_REF (mt); - if (ipa_get_param_count (info) == 0) + if (ipa_get_param_count (info) == 0 || info->modified_flags) return; count = ipa_get_param_count (info); @@ -244,7 +257,7 @@ ipa_compute_jump_functions (struct cgraph_edge *cs) call_expr_arg_iterator iter; struct ipa_edge_args *args = IPA_EDGE_REF (cs); - if (ipa_get_cs_argument_count (args) == 0) + if (ipa_get_cs_argument_count (args) == 0 || args->jump_functions) return; args->jump_functions = XCNEWVEC (struct ipa_jump_func, ipa_get_cs_argument_count (args)); @@ -316,74 +329,184 @@ ipa_compute_jump_functions (struct cgraph_edge *cs) } } -/* Allocate and initialize ipa_node_params structure for the given cgraph - node. */ +/* Frees all dynamically allocated structures that the argument info points + to. */ void -ipa_create_node_params (struct cgraph_node *node) +ipa_free_edge_args_substructures (struct ipa_edge_args *args) { - node->aux = xcalloc (1, sizeof (struct ipa_node_params)); + if (args->jump_functions) + free (args->jump_functions); + + memset (args, 0, sizeof (*args)); } -/* Allocate and initialize ipa_node_params structure for all - nodes in callgraph. */ +/* Free all ipa_edge structures. */ void -ipa_create_all_node_params (void) +ipa_free_all_edge_args (void) { - struct cgraph_node *node; + int i; + struct ipa_edge_args *args; - for (node = cgraph_nodes; node; node = node->next) - ipa_create_node_params (node); + for (i = 0; + VEC_iterate (ipa_edge_args_t, ipa_edge_args_vector, i, args); + i++) + ipa_free_edge_args_substructures (args); + + VEC_free (ipa_edge_args_t, heap, ipa_edge_args_vector); + ipa_edge_args_vector = NULL; } -/* Allocate and initialize ipa_edge structure. */ +/* Frees all dynamically allocated structures that the param info points + to. */ void -ipa_create_all_edge_args (void) +ipa_free_node_params_substructures (struct ipa_node_params *info) { - struct cgraph_node *node; - struct cgraph_edge *cs; - - for (node = cgraph_nodes; node; node = node->next) - for (cs = node->callees; cs; cs = cs->next_callee) - cs->aux = xcalloc (1, sizeof (struct ipa_edge_args)); + if (info->ipcp_lattices) + free (info->ipcp_lattices); + if (info->param_decls) + free (info->param_decls); + if (info->modified_flags) + free (info->modified_flags); + + memset (info, 0, sizeof (*info)); } -/* Free ipa_edge structure. */ +/* Free all ipa_node_params structures. */ void -ipa_free_all_edge_args (void) +ipa_free_all_node_params (void) { - struct cgraph_node *node; - struct cgraph_edge *cs; + int i; + struct ipa_node_params *info; - for (node = cgraph_nodes; node; node = node->next) - for (cs = node->callees; cs; cs = cs->next_callee) - if (cs->aux) - { - if (IPA_EDGE_REF (cs)->jump_functions) - free (IPA_EDGE_REF (cs)->jump_functions); - free (cs->aux); - cs->aux = NULL; - } + for (i = 0; + VEC_iterate (ipa_node_params_t, ipa_node_params_vector, i, info); + i++) + ipa_free_node_params_substructures (info); + + VEC_free (ipa_node_params_t, heap, ipa_node_params_vector); + ipa_node_params_vector = NULL; +} + +/* Hook that is called by cgraph.c when an edge is removed. */ +static void +ipa_edge_removal_hook (struct cgraph_edge *cs, + void *data __attribute__ ((unused))) +{ + ipa_free_edge_args_substructures (IPA_EDGE_REF (cs)); } -/* Free ipa data structures of ipa_node_params and ipa_edge_args. */ +/* Hook that is called by cgraph.c when a node is removed. */ +static void +ipa_node_removal_hook (struct cgraph_node *node, + void *data __attribute__ ((unused))) +{ + ipa_free_node_params_substructures (IPA_NODE_REF (node)); +} + +/* Helper function to duplicate an array of size N that is at SRC and store a + pointer to it to DST. Nothing is done if SRC is NULL. */ +static void * +duplicate_array (void *src, size_t n) +{ + void *p; + + if (!src) + return NULL; + + p = xcalloc (1, n); + memcpy (p, src, n); + return p; +} + +/* Hook that is called by cgraph.c when a node is duplicated. */ +static void +ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, + void *data) +{ + struct ipa_edge_args *old_args, *new_args; + int arg_count; + + ipa_check_create_edge_args (); + + old_args = IPA_EDGE_REF (src); + new_args = IPA_EDGE_REF (dst); + + arg_count = ipa_get_cs_argument_count (old_args); + ipa_set_cs_argument_count (new_args, arg_count); + new_args->jump_functions = (struct ipa_jump_func *) + duplicate_array (old_args->jump_functions, + sizeof (struct ipa_jump_func) * arg_count); + data = data; /* Suppressing compiler warning. */ +} + +/* Hook that is called by cgraph.c when a node is duplicated. */ +static void +ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, + void *data) +{ + struct ipa_node_params *old_info, *new_info; + int param_count; + + ipa_check_create_node_params (); + old_info = IPA_NODE_REF (src); + new_info = IPA_NODE_REF (dst); + param_count = ipa_get_param_count (old_info); + + ipa_set_param_count (new_info, param_count); + new_info->ipcp_lattices = (struct ipcp_lattice *) + duplicate_array (old_info->ipcp_lattices, + sizeof (struct ipcp_lattice) * param_count); + new_info->param_decls = (tree *) + duplicate_array (old_info->param_decls, sizeof (tree) * param_count); + new_info->modified_flags = (bool *) + duplicate_array (old_info->modified_flags, sizeof (bool) * param_count); + + new_info->ipcp_orig_node = old_info->ipcp_orig_node; + new_info->count_scale = old_info->count_scale; + + data = data; /* Suppressing compiler warning. */ +} + +/* Register our cgraph hooks if they are not already there. */ void -ipa_free_all_node_params (void) +ipa_register_cgraph_hooks (void) { - struct cgraph_node *node; + if (!edge_removal_hook_holder) + edge_removal_hook_holder = + cgraph_add_edge_removal_hook (&ipa_edge_removal_hook, NULL); + if (!node_removal_hook_holder) + node_removal_hook_holder = + cgraph_add_node_removal_hook (&ipa_node_removal_hook, NULL); + if (!edge_duplication_hook_holder) + edge_duplication_hook_holder = + cgraph_add_edge_duplication_hook (&ipa_edge_duplication_hook, NULL); + if (!node_duplication_hook_holder) + node_duplication_hook_holder = + cgraph_add_node_duplication_hook (&ipa_node_duplication_hook, NULL); +} - for (node = cgraph_nodes; node; node = node->next) - { - if (node->aux == NULL) - continue; - if (IPA_NODE_REF (node)->ipcp_lattices) - free (IPA_NODE_REF (node)->ipcp_lattices); - if (IPA_NODE_REF (node)->param_decls) - free (IPA_NODE_REF (node)->param_decls); - if (IPA_NODE_REF (node)->modified_flags) - free (IPA_NODE_REF (node)->modified_flags); - free (node->aux); - node->aux = NULL; - } +/* Unregister our cgraph hooks if they are not already there. */ +static void +ipa_unregister_cgraph_hooks (void) +{ + cgraph_remove_edge_removal_hook (edge_removal_hook_holder); + edge_removal_hook_holder = NULL; + cgraph_remove_node_removal_hook (node_removal_hook_holder); + node_removal_hook_holder = NULL; + cgraph_remove_edge_duplication_hook (edge_duplication_hook_holder); + edge_duplication_hook_holder = NULL; + cgraph_remove_node_duplication_hook (node_duplication_hook_holder); + node_duplication_hook_holder = NULL; +} + +/* Free all ipa_node_params and all ipa_edge_args structures if they are no + longer needed after ipa-cp. */ +void +free_all_ipa_structures_after_ipa_cp (void) +{ + ipa_free_all_edge_args (); + ipa_free_all_node_params (); + ipa_unregister_cgraph_hooks (); } /* Print ipa_tree_map data structures of all functions in the diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index a81418d7f47..e442698bd3a 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #define IPA_PROP_H #include "tree.h" +#include "vec.h" /* The following definitions and interfaces are used by interprocedural analyses. */ @@ -100,14 +101,6 @@ struct ipa_replace_map bool ref_p; }; -/* Return the field in cgraph_node/cgraph_edge struct that points - to ipa_node_params/ipa_edge_args struct. */ -#define IPA_NODE_REF(MT) ((struct ipa_node_params *)(MT)->aux) -#define IPA_EDGE_REF(EDGE) ((struct ipa_edge_args *)(EDGE)->aux) -/* This macro checks validity of index returned by - ipa_get_param_decl_index function. */ -#define IS_VALID_JUMP_FUNC_INDEX(I) ((I) != -1) - /* ipa_node_params stores information related to formal parameters of functions and some other information for interprocedural passes that operate on parameters (such as ipa-cp). */ @@ -229,6 +222,71 @@ ipa_get_ith_jump_func (struct ipa_edge_args *args, int i) return &args->jump_functions[i]; } +/* Vectors need to have typedefs of structures. */ +typedef struct ipa_node_params ipa_node_params_t; +typedef struct ipa_edge_args ipa_edge_args_t; + +/* Types of vectors hodling the infos. */ +DEF_VEC_O (ipa_node_params_t); +DEF_VEC_ALLOC_O (ipa_node_params_t, heap); +DEF_VEC_O (ipa_edge_args_t); +DEF_VEC_ALLOC_O (ipa_edge_args_t, heap); + +/* Vector where the parameter infos are actually stored. */ +extern VEC (ipa_node_params_t, heap) *ipa_node_params_vector; +/* Vector where the parameter infos are actually stored. */ +extern VEC (ipa_edge_args_t, heap) *ipa_edge_args_vector; + +/* Return the associated parameter/argument info corresponding to the given + node/edge. */ +#define IPA_NODE_REF(NODE) (VEC_index (ipa_node_params_t, \ + ipa_node_params_vector, (NODE)->uid)) +#define IPA_EDGE_REF(EDGE) (VEC_index (ipa_edge_args_t, \ + ipa_edge_args_vector, (EDGE)->uid)) +/* This macro checks validity of index returned by + ipa_get_param_decl_index function. */ +#define IS_VALID_JUMP_FUNC_INDEX(I) ((I) != -1) + +/* Creating and freeing ipa_node_params and ipa_edge_args. */ +void ipa_create_all_node_params (void); +void ipa_create_all_edge_args (void); +void ipa_free_edge_args_substructures (struct ipa_edge_args *); +void ipa_free_node_params_substructures (struct ipa_node_params *); +void ipa_free_all_node_params (void); +void ipa_free_all_edge_args (void); +void free_all_ipa_structures_after_ipa_cp (void); +void ipa_register_cgraph_hooks (void); + +/* This function ensures the array of node param infos is big enough to + accomdate a structure for all nodes and realloacates it if not. */ +static inline void +ipa_check_create_node_params (void) +{ + if (!ipa_node_params_vector) + ipa_node_params_vector = VEC_alloc (ipa_node_params_t, heap, + cgraph_max_uid); + + if (VEC_length (ipa_node_params_t, ipa_node_params_vector) + <= (unsigned) cgraph_max_uid) + VEC_safe_grow_cleared (ipa_node_params_t, heap, + ipa_node_params_vector, cgraph_max_uid + 1); +} + +/* This function ensures the array of adge arguments infos is big enough to + accomdate a structure for all edges and realloacates it if not. */ +static inline void +ipa_check_create_edge_args (void) +{ + if (!ipa_edge_args_vector) + ipa_edge_args_vector = VEC_alloc (ipa_edge_args_t, heap, + cgraph_edge_max_uid); + + if (VEC_length (ipa_edge_args_t, ipa_edge_args_vector) + <= (unsigned) cgraph_edge_max_uid) + VEC_safe_grow_cleared (ipa_edge_args_t, heap, ipa_edge_args_vector, + cgraph_edge_max_uid + 1); +} + /* A function list element. It is used to create a temporary worklist used in the propagation stage of IPCP. (can be used for more IPA optimizations) */ struct ipa_func_list @@ -251,13 +309,6 @@ void ipa_count_formal_params (struct cgraph_node *); void ipa_create_param_decls_array (struct cgraph_node *); void ipa_detect_param_modifications (struct cgraph_node *); -/* Creating and freeing ipa_node_params and ipa_edge_args. */ -void ipa_create_node_params (struct cgraph_node *); -void ipa_free_all_node_params (void); -void ipa_create_all_node_params (void); -void ipa_create_all_edge_args (void); -void ipa_free_all_edge_args (void); - /* Debugging interface. */ void ipa_print_all_tree_maps (FILE *); void ipa_print_all_params_modified (FILE *); diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 33ac01f7a7c..f0f57e76390 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,21 @@ +2008-07-06 Tom Tromey <tromey@redhat.com> + + * Make-lang.in (java/parse.o-warn): Remove. + (java/jcf-io.o-warn): Remove. + +2008-07-05 Tom Tromey <tromey@redhat.com> + + * jcf-io.c: Don't include fnmatch.h. Don't use JCF_USE_SCANDIR. + (compare_path): Remove. + (java_or_class_file): Likewise. + (memoized_dirlist_entry): Likewise. + (memoized_dirlist_hash): Likewise. + (memoized_dirlist_lookup_eq): Likewise. + (memoized_dirlists): Likewise. + (caching_stat): Likewise. + (find_class): Use stat. + * jcf.h (JCF_USE_SCANDIR): Remove. + 2008-06-30 Joshua Sumali <jsumali@redhat.com> * Make-lang.in (JAVA_MANFILES): Add doc/aot-compile.1 and diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in index cab40afb959..6f0c4179f97 100644 --- a/gcc/java/Make-lang.in +++ b/gcc/java/Make-lang.in @@ -98,12 +98,6 @@ java-warn = $(STRICT_WARN) # String length warnings jvspec.o-warn = -Wno-error -# Bison-1.75 output often yields (harmless) -Wtraditional warnings -java/parse.o-warn = -Wno-error - -# java/jcf-io.c contains a -Wc++compat warning. -java/jcf-io.o-warn = -Wno-error - jc1$(exeext): $(JAVA_OBJS) $(BACKEND) $(LIBDEPS) attribs.o rm -f $@ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \ diff --git a/gcc/java/jcf-io.c b/gcc/java/jcf-io.c index 52120971fa2..b968214e509 100644 --- a/gcc/java/jcf-io.c +++ b/gcc/java/jcf-io.c @@ -34,10 +34,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "toplev.h" #include "java-tree.h" #include "hashtab.h" -#if JCF_USE_SCANDIR #include <dirent.h> -#include <fnmatch.h> -#endif #include "zlib.h" @@ -283,145 +280,6 @@ find_classfile (char *filename, JCF *jcf, const char *dep_name) return open_class (filename, jcf, fd, dep_name); } -#if JCF_USE_SCANDIR - -/* A comparison function (as for qsort) that compares KEY (a char * - giving the basename of a file) with the name stored in ENTRY (a - dirent **). */ - -static int -compare_path (const void *key, const void *entry) -{ - return strcmp ((const char *) key, - (*((const struct dirent *const*) entry))->d_name); -} - -/* Returns nonzero if ENTRY names a .java or .class file. */ - -static int -java_or_class_file (const struct dirent *entry) -{ - const char *base = lbasename (entry->d_name); - return (fnmatch ("*.java", base, 0) == 0 || - fnmatch ("*.class", base, 0) == 0); -} - -/* Information about the files present in a particular directory. */ -typedef struct memoized_dirlist_entry -{ - /* The name of the directory. */ - const char *dir; - /* The number of .java and .class files present, or -1 if we could - not, for some reason, obtain the list. */ - int num_files; - /* The .java and .class files in the directory, in alphabetical - order. */ - struct dirent **files; -} memoized_dirlist_entry; - -/* A hash function for a memoized_dirlist_entry. */ -static hashval_t -memoized_dirlist_hash (const void *entry) -{ - const memoized_dirlist_entry *mde = (const memoized_dirlist_entry *) entry; - return htab_hash_string (mde->dir); -} - -/* Returns true if ENTRY (a memoized_dirlist_entry *) corresponds to - the directory given by KEY (a char *) giving the directory - name. */ - -static int -memoized_dirlist_lookup_eq (const void *entry, const void *key) -{ - return strcmp ((const char *) key, - ((const memoized_dirlist_entry *) entry)->dir) == 0; -} - -/* A hash table mapping directory names to the lists of .java and - .class files in that directory. */ - -static htab_t memoized_dirlists; - -#endif - -/* Like stat, but avoids actually making the stat system call if we - know that it cannot succeed. FILENAME and BUF are as for stat. */ - -static int -caching_stat (char *filename, struct stat *buf) -{ -#if JCF_USE_SCANDIR - char *sep; - char origsep = 0; - char *base; - memoized_dirlist_entry *dent; - void **slot; - struct memoized_dirlist_entry temp; - - /* If the hashtable has not already been created, create it now. */ - if (!memoized_dirlists) - memoized_dirlists = htab_create (37, - memoized_dirlist_hash, - memoized_dirlist_lookup_eq, - NULL); - - /* Get the name of the directory. */ - sep = strrchr (filename, DIR_SEPARATOR); -#ifdef DIR_SEPARATOR_2 - if (! sep) - sep = strrchr (filename, DIR_SEPARATOR_2); -#endif - if (sep) - { - origsep = *sep; - *sep = '\0'; - base = sep + 1; - } - else - base = filename; - - /* Obtain the entry for this directory from the hash table. This - approach is ok since we know that the hash function only looks at - the directory name. */ - temp.dir = filename; - temp.num_files = 0; - temp.files = NULL; - slot = htab_find_slot (memoized_dirlists, &temp, INSERT); - if (!*slot) - { - /* We have not already scanned this directory; scan it now. */ - dent = XNEW (memoized_dirlist_entry); - dent->dir = xstrdup (filename); - /* Unfortunately, scandir is not fully standardized. In - particular, the type of the function pointer passed as the - third argument sometimes takes a "const struct dirent *" - parameter, and sometimes just a "struct dirent *". We cast - to (void *) and use __extension__ so that either way it is - quietly accepted. FIXME: scandir is not in POSIX. */ - dent->num_files = __extension__ scandir (filename, &dent->files, - (void *) java_or_class_file, - alphasort); - *slot = dent; - } - else - dent = *((memoized_dirlist_entry **) slot); - - /* Put the separator back. */ - if (sep) - *sep = origsep; - - /* If the file is not in the list, there is no need to stat it; it - does not exist. */ - if (dent->num_files != -1 - && !bsearch (base, dent->files, dent->num_files, - sizeof (struct dirent *), compare_path)) - return -1; -#endif - - return stat (filename, buf); -} - /* Returns 1 if the CLASSNAME (really a char *) matches the name stored in TABLE_ENTRY (also a char *). */ @@ -521,7 +379,7 @@ find_class (const char *classname, int classname_length, JCF *jcf) else continue; } - klass = caching_stat(buffer, &class_buf); + klass = stat (buffer, &class_buf); } } diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h index d4de2c57d54..40bbd725d45 100644 --- a/gcc/java/jcf.h +++ b/gcc/java/jcf.h @@ -1,6 +1,6 @@ /* Utility macros to read Java(TM) .class files and byte codes. Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2006, 2007 Free Software Foundation, Inc. + 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of GCC. @@ -45,14 +45,6 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #define JCF_word JCF_u4 #endif -/* If we have both "scandir" and "alphasort", we can cache directory - listings to reduce the time taken to search the classpath. */ -#if defined(HAVE_SCANDIR) && defined(HAVE_ALPHASORT) -#define JCF_USE_SCANDIR 1 -#else -#define JCF_USE_SCANDIR 0 -#endif - /* On case-insensitive file systems, we need to ensure that a request to open a .java or .class file is honored only if the file to be opened is of the exact case we are asking for. In other words, we diff --git a/gcc/jump.c b/gcc/jump.c index 23d183e932c..595363b1adb 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -1068,8 +1068,7 @@ mark_jump_label_1 (rtx x, rtx insn, bool in_mem, bool is_target) a label, except for the primary target of a jump, must have such a note. */ if (! find_reg_note (insn, kind, label)) - REG_NOTES (insn) - = gen_rtx_INSN_LIST (kind, label, REG_NOTES (insn)); + add_reg_note (insn, kind, label); } } return; diff --git a/gcc/libgcc-std.ver b/gcc/libgcc-std.ver index 89be00cf3be..2df39f63e37 100644 --- a/gcc/libgcc-std.ver +++ b/gcc/libgcc-std.ver @@ -1800,3 +1800,88 @@ GCC_4.3.0 { __satfractunstiuda __satfractunstiuta } + +%inherit GCC_4.4.0 GCC_4.3.0 +GCC_4.4.0 { + __sync_fetch_and_add_1 + __sync_fetch_and_sub_1 + __sync_fetch_and_or_1 + __sync_fetch_and_and_1 + __sync_fetch_and_xor_1 + __sync_fetch_and_nand_1 + __sync_add_and_fetch_1 + __sync_sub_and_fetch_1 + __sync_or_and_fetch_1 + __sync_and_and_fetch_1 + __sync_xor_and_fetch_1 + __sync_nand_and_fetch_1 + __sync_bool_compare_and_swap_1 + __sync_val_compare_and_swap_1 + __sync_lock_test_and_set_1 + + __sync_fetch_and_add_2 + __sync_fetch_and_sub_2 + __sync_fetch_and_or_2 + __sync_fetch_and_and_2 + __sync_fetch_and_xor_2 + __sync_fetch_and_nand_2 + __sync_add_and_fetch_2 + __sync_sub_and_fetch_2 + __sync_or_and_fetch_2 + __sync_and_and_fetch_2 + __sync_xor_and_fetch_2 + __sync_nand_and_fetch_2 + __sync_bool_compare_and_swap_2 + __sync_val_compare_and_swap_2 + __sync_lock_test_and_set_2 + + __sync_fetch_and_add_4 + __sync_fetch_and_sub_4 + __sync_fetch_and_or_4 + __sync_fetch_and_and_4 + __sync_fetch_and_xor_4 + __sync_fetch_and_nand_4 + __sync_add_and_fetch_4 + __sync_sub_and_fetch_4 + __sync_or_and_fetch_4 + __sync_and_and_fetch_4 + __sync_xor_and_fetch_4 + __sync_nand_and_fetch_4 + __sync_bool_compare_and_swap_4 + __sync_val_compare_and_swap_4 + __sync_lock_test_and_set_4 + + __sync_fetch_and_add_8 + __sync_fetch_and_sub_8 + __sync_fetch_and_or_8 + __sync_fetch_and_and_8 + __sync_fetch_and_xor_8 + __sync_fetch_and_nand_8 + __sync_add_and_fetch_8 + __sync_sub_and_fetch_8 + __sync_or_and_fetch_8 + __sync_and_and_fetch_8 + __sync_xor_and_fetch_8 + __sync_nand_and_fetch_8 + __sync_bool_compare_and_swap_8 + __sync_val_compare_and_swap_8 + __sync_lock_test_and_set_8 + + __sync_fetch_and_add_16 + __sync_fetch_and_sub_16 + __sync_fetch_and_or_16 + __sync_fetch_and_and_16 + __sync_fetch_and_xor_16 + __sync_fetch_and_nand_16 + __sync_add_and_fetch_16 + __sync_sub_and_fetch_16 + __sync_or_and_fetch_16 + __sync_and_and_fetch_16 + __sync_xor_and_fetch_16 + __sync_nand_and_fetch_16 + __sync_bool_compare_and_swap_16 + __sync_val_compare_and_swap_16 + __sync_lock_test_and_set_16 + + __sync_synchronize +} diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c index c6e0540d15f..293b3ae3776 100644 --- a/gcc/loop-doloop.c +++ b/gcc/loop-doloop.c @@ -321,9 +321,8 @@ add_test (rtx cond, edge *e, basic_block dest) JUMP_LABEL (jump) = label; /* The jump is supposed to handle an unlikely special case. */ - REG_NOTES (jump) - = gen_rtx_EXPR_LIST (REG_BR_PROB, - const0_rtx, REG_NOTES (jump)); + add_reg_note (jump, REG_BR_PROB, const0_rtx); + LABEL_NUSES (label)++; make_edge (bb, dest, (*e)->flags & ~EDGE_FALLTHRU); @@ -518,18 +517,14 @@ doloop_modify (struct loop *loop, struct niter_desc *desc, /* Add a REG_NONNEG note if the actual or estimated maximum number of iterations is non-negative. */ if (nonneg) - { - REG_NOTES (jump_insn) - = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX, REG_NOTES (jump_insn)); - } + add_reg_note (jump_insn, REG_NONNEG, NULL_RTX); + /* Update the REG_BR_PROB note. */ if (true_prob_val) { /* Seems safer to use the branch probability. */ - REG_NOTES (jump_insn) = - gen_rtx_EXPR_LIST (REG_BR_PROB, - GEN_INT (desc->in_edge->probability), - REG_NOTES (jump_insn)); + add_reg_note (jump_insn, REG_BR_PROB, + GEN_INT (desc->in_edge->probability)); } } diff --git a/gcc/loop-unswitch.c b/gcc/loop-unswitch.c index 54c39a5698a..9d66d41db6e 100644 --- a/gcc/loop-unswitch.c +++ b/gcc/loop-unswitch.c @@ -125,8 +125,8 @@ compare_and_jump_seq (rtx op0, rtx op1, enum rtx_code comp, rtx label, int prob, JUMP_LABEL (jump) = label; LABEL_NUSES (label)++; } - REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob), - REG_NOTES (jump)); + add_reg_note (jump, REG_BR_PROB, GEN_INT (prob)); + seq = get_insns (); end_sequence (); diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c index 67a95984fab..57205b51e61 100644 --- a/gcc/lower-subreg.c +++ b/gcc/lower-subreg.c @@ -551,8 +551,7 @@ move_eh_region_note (rtx insn, rtx insns) || (flag_non_call_exceptions && INSN_P (p) && may_trap_p (PATTERN (p)))) - REG_NOTES (p) = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (note, 0), - REG_NOTES (p)); + add_reg_note (p, REG_EH_REGION, XEXP (note, 0)); } } diff --git a/gcc/mkmap-symver.awk b/gcc/mkmap-symver.awk index 855043f7e6c..4877e905147 100644 --- a/gcc/mkmap-symver.awk +++ b/gcc/mkmap-symver.awk @@ -46,7 +46,8 @@ state == "nm" && ($1 == "U" || $2 == "U") { } state == "nm" && NF == 3 { - def[$3] = 1; + split ($3, s, "@") + def[s[1]] = 1; sawsymbol = 1; next; } @@ -82,10 +83,13 @@ $1 == "}" { { sym = prefix $1; + symbols[sym] = 1 if (thislib != "%exclude") - ver[sym] = thislib; - else - delete ver[sym]; + ver[sym, thislib] = 1; + else { + for (l in libs) + ver[sym, l] = 0; + } next; } @@ -107,8 +111,8 @@ function output(lib) { output(inherit[lib]); empty=1 - for (sym in ver) - if ((ver[sym] == lib) && (sym in def)) + for (sym in symbols) + if ((ver[sym, lib] != 0) && (sym in def)) { if (empty) { diff --git a/gcc/optabs.c b/gcc/optabs.c index 32a6396bd70..6e8c6cf3d21 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -3879,8 +3879,7 @@ emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv) if (note != 0) XEXP (note, 0) = constm1_rtx; else - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx, - REG_NOTES (insn)); + add_reg_note (insn, REG_EH_REGION, constm1_rtx); } /* First emit all insns that set pseudos. Remove them from the list as diff --git a/gcc/opts.c b/gcc/opts.c index 0bea9e4e94b..c26260acdd7 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -903,6 +903,9 @@ decode_options (unsigned int argc, const char **argv) /* Allow more virtual operators to increase alias precision. */ set_param_value ("max-aliased-vops", 500); + + /* Track fields in field-sensitive alias analysis. */ + set_param_value ("max-fields-for-field-sensitive", 100); } if (optimize >= 3) diff --git a/gcc/predict.c b/gcc/predict.c index ca7f9448d01..f85786e1a1d 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -263,12 +263,10 @@ predict_insn (rtx insn, enum br_predictor predictor, int probability) if (!flag_guess_branch_prob) return; - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_BR_PRED, - gen_rtx_CONCAT (VOIDmode, - GEN_INT ((int) predictor), - GEN_INT ((int) probability)), - REG_NOTES (insn)); + add_reg_note (insn, REG_BR_PRED, + gen_rtx_CONCAT (VOIDmode, + GEN_INT ((int) predictor), + GEN_INT ((int) probability))); } /* Predict insn by given predictor. */ @@ -561,9 +559,7 @@ combine_predictions_for_insn (rtx insn, basic_block bb) if (!prob_note) { - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_BR_PROB, - GEN_INT (combined_probability), REG_NOTES (insn)); + add_reg_note (insn, REG_BR_PROB, GEN_INT (combined_probability)); /* Save the prediction into CFG in case we are seeing non-degenerated conditional jump. */ @@ -1948,7 +1944,8 @@ gate_estimate_probability (void) tree build_predict_expr (enum br_predictor predictor, enum prediction taken) { - tree t = build1 (PREDICT_EXPR, NULL_TREE, build_int_cst (NULL, predictor)); + tree t = build1 (PREDICT_EXPR, void_type_node, + build_int_cst (NULL, predictor)); PREDICT_EXPR_OUTCOME (t) = taken; return t; } diff --git a/gcc/recog.c b/gcc/recog.c index a176ed30af6..3ddfd86c635 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -3045,10 +3045,9 @@ peephole2_optimize (void) { case REG_NORETURN: case REG_SETJMP: - REG_NOTES (new_insn) - = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note), - XEXP (note, 0), - REG_NOTES (new_insn)); + add_reg_note (new_insn, REG_NOTE_KIND (note), + XEXP (note, 0)); + break; default: /* Discard all other reg notes. */ break; @@ -3096,10 +3095,7 @@ peephole2_optimize (void) && !find_reg_note (x, REG_EH_REGION, NULL))) { if (note) - REG_NOTES (x) - = gen_rtx_EXPR_LIST (REG_EH_REGION, - XEXP (note, 0), - REG_NOTES (x)); + add_reg_note (x, REG_EH_REGION, XEXP (note, 0)); if (x != BB_END (bb) && eh_edge) { diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index ffa06fd5752..4b5e422e207 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -788,9 +788,7 @@ emit_pop_insn (rtx insn, stack regstack, rtx reg, enum emit_where where) else pop_insn = emit_insn_before (pop_rtx, insn); - REG_NOTES (pop_insn) - = gen_rtx_EXPR_LIST (REG_DEAD, FP_MODE_REG (FIRST_STACK_REG, DFmode), - REG_NOTES (pop_insn)); + add_reg_note (pop_insn, REG_DEAD, FP_MODE_REG (FIRST_STACK_REG, DFmode)); regstack->reg[regstack->top - (hard_regno - FIRST_STACK_REG)] = regstack->reg[regstack->top]; @@ -1064,8 +1062,7 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat) push_rtx = gen_movxf (top_stack_reg, top_stack_reg); emit_insn_before (push_rtx, insn); - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg, - REG_NOTES (insn)); + add_reg_note (insn, REG_DEAD, top_stack_reg); } replace_reg (psrc, FIRST_STACK_REG); diff --git a/gcc/regmove.c b/gcc/regmove.c index 4a53defed24..7de8d0d5b98 100644 --- a/gcc/regmove.c +++ b/gcc/regmove.c @@ -200,9 +200,8 @@ try_auto_increment (rtx insn, rtx inc_insn, rtx inc_insn_set, rtx reg, if (note) PUT_MODE (note, REG_UNUSED); - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_INC, - reg, REG_NOTES (insn)); + add_reg_note (insn, REG_INC, reg); + if (! inc_insn_set) delete_insn (inc_insn); return 1; diff --git a/gcc/reload.c b/gcc/reload.c index 9ab01375a91..e426d3634f6 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -4145,9 +4145,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, && (!JUMP_P (insn) || !label_is_jump_target_p (XEXP (substitution, 0), insn))) - REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, - XEXP (substitution, 0), - REG_NOTES (insn)); + add_reg_note (insn, REG_LABEL_OPERAND, XEXP (substitution, 0)); } else retval |= (substed_operand[i] != *recog_data.operand_loc[i]); diff --git a/gcc/reload1.c b/gcc/reload1.c index 297acbf8aa5..f449ffa9c32 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -4000,8 +4000,7 @@ fixup_eh_region_note (rtx insn, rtx prev, rtx next) if (INSN_P (i) && i != insn && may_trap_p (PATTERN (i))) { trap_count++; - REG_NOTES (i) - = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (note, 0), REG_NOTES (i)); + add_reg_note (i, REG_EH_REGION, XEXP (note, 0)); } } @@ -4235,9 +4234,7 @@ reload_as_needed (int live_known) } if (n == 1) { - REG_NOTES (p) - = gen_rtx_EXPR_LIST (REG_INC, reload_reg, - REG_NOTES (p)); + add_reg_note (p, REG_INC, reload_reg); /* Mark this as having an output reload so that the REG_INC processing code below won't invalidate the reload for inheritance. */ @@ -8535,8 +8532,7 @@ add_auto_inc_notes (rtx insn, rtx x) if (code == MEM && auto_inc_p (XEXP (x, 0))) { - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_INC, XEXP (XEXP (x, 0), 0), REG_NOTES (insn)); + add_reg_note (insn, REG_INC, XEXP (XEXP (x, 0), 0)); return; } @@ -8563,9 +8559,7 @@ copy_eh_notes (rtx insn, rtx x) for (; x != 0; x = NEXT_INSN (x)) { if (may_trap_p (PATTERN (x))) - REG_NOTES (x) - = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (eh_note, 0), - REG_NOTES (x)); + add_reg_note (x, REG_EH_REGION, XEXP (eh_note, 0)); } } } diff --git a/gcc/reorg.c b/gcc/reorg.c index 7135a188574..25f410aad2d 100644 --- a/gcc/reorg.c +++ b/gcc/reorg.c @@ -3217,9 +3217,7 @@ delete_prior_computation (rtx note, rtx insn) { int i; - REG_NOTES (our_prev) - = gen_rtx_EXPR_LIST (REG_UNUSED, reg, - REG_NOTES (our_prev)); + add_reg_note (our_prev, REG_UNUSED, reg); for (i = dest_regno; i < dest_endregno; i++) if (! find_regno_note (our_prev, REG_UNUSED, i)) @@ -3281,8 +3279,7 @@ delete_computation (rtx insn) delete_computation (prev); else /* Otherwise, show that cc0 won't be used. */ - REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_UNUSED, - cc0_rtx, REG_NOTES (prev)); + add_reg_note (prev, REG_UNUSED, cc0_rtx); } } #endif @@ -4024,9 +4021,7 @@ dbr_schedule (rtx first) continue; pred_flags = get_jump_flags (insn, JUMP_LABEL (insn)); - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_BR_PRED, - GEN_INT (pred_flags), - REG_NOTES (insn)); + add_reg_note (insn, REG_BR_PRED, GEN_INT (pred_flags)); } free_resource_info (); free (uid_to_ruid); diff --git a/gcc/resource.c b/gcc/resource.c index 05308491f61..009fb6e609b 100644 --- a/gcc/resource.c +++ b/gcc/resource.c @@ -266,13 +266,10 @@ mark_referenced_resources (rtx x, struct resources *res, return; case UNSPEC_VOLATILE: + case TRAP_IF: case ASM_INPUT: /* Traditional asm's are always volatile. */ res->volatil = 1; - return; - - case TRAP_IF: - res->volatil = 1; break; case ASM_OPERANDS: diff --git a/gcc/rtl.h b/gcc/rtl.h index 2e0884f8f56..b2b561c3421 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1755,6 +1755,7 @@ extern rtx find_reg_equal_equiv_note (const_rtx); extern rtx find_constant_src (const_rtx); extern int find_reg_fusage (const_rtx, enum rtx_code, const_rtx); extern int find_regno_fusage (const_rtx, enum rtx_code, unsigned int); +extern void add_reg_note (rtx, enum reg_note, rtx); extern void remove_note (rtx, const_rtx); extern void remove_reg_equal_equiv_notes (rtx); extern int side_effects_p (const_rtx); diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index dec7daf0e3d..d569ff04b2b 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -1842,6 +1842,34 @@ find_regno_fusage (const_rtx insn, enum rtx_code code, unsigned int regno) } +/* Add register note with kind KIND and datum DATUM to INSN. */ + +void +add_reg_note (rtx insn, enum reg_note kind, rtx datum) +{ + rtx note; + + switch (kind) + { + case REG_CC_SETTER: + case REG_CC_USER: + case REG_LABEL_TARGET: + case REG_LABEL_OPERAND: + /* These types of register notes use an INSN_LIST rather than an + EXPR_LIST, so that copying is done right and dumps look + better. */ + note = alloc_INSN_LIST (datum, REG_NOTES (insn)); + PUT_REG_NOTE_KIND (note, kind); + break; + + default: + note = alloc_EXPR_LIST (kind, datum, REG_NOTES (insn)); + break; + } + + REG_NOTES (insn) = note; +} + /* Remove register note NOTE from the REG_NOTES of INSN. */ void diff --git a/gcc/target-def.h b/gcc/target-def.h index 2692e94aabc..7ffb1346021 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -520,6 +520,8 @@ #define TARGET_MACHINE_DEPENDENT_REORG 0 #define TARGET_BUILD_BUILTIN_VA_LIST std_build_builtin_va_list +#define TARGET_FN_ABI_VA_LIST std_fn_abi_va_list +#define TARGET_CANONICAL_VA_LIST_TYPE std_canonical_va_list_type #define TARGET_EXPAND_BUILTIN_VA_START 0 #define TARGET_GET_PCH_VALIDITY default_get_pch_validity @@ -820,6 +822,8 @@ TARGET_CC_MODES_COMPATIBLE, \ TARGET_MACHINE_DEPENDENT_REORG, \ TARGET_BUILD_BUILTIN_VA_LIST, \ + TARGET_FN_ABI_VA_LIST, \ + TARGET_CANONICAL_VA_LIST_TYPE, \ TARGET_EXPAND_BUILTIN_VA_START, \ TARGET_GIMPLIFY_VA_ARG_EXPR, \ TARGET_GET_PCH_VALIDITY, \ diff --git a/gcc/target.h b/gcc/target.h index 012d1c0099b..11852430c8d 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -697,6 +697,12 @@ struct gcc_target /* Create the __builtin_va_list type. */ tree (* build_builtin_va_list) (void); + /* Get the cfun/fndecl calling abi __builtin_va_list type. */ + tree (* fn_abi_va_list) (tree); + + /* Get the __builtin_va_list type dependent on input type. */ + tree (* canonical_va_list_type) (tree); + /* Expand the __builtin_va_start builtin. */ void (* expand_builtin_va_start) (tree valist, rtx nextarg); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e8175a12083..f73e0443f8a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,264 @@ +2008-07-07 H.J. Lu <hongjiu.lu@intel.com> + + * gcc.dg/compat/struct-layout-1_generate.c (vector_types): Add + v32qi, v16hi, v8si, v4di, v8sf, v4df, u32qi, u16hi, u8si, u4di, + u8sf and u4df. + + * gcc.dg/compat/union-m128-1_main.c: Run only on x86. Remove + __x86_64__ check. Include "cpuid.h". + (main): Check SSE2 at runtime. + + * gcc.dg/compat/union-m128-1_x.c: Compile with -msse2. Remove + __x86_64__ check. + * gcc.dg/compat/union-m128-1_y.c: Likewise. + + * gcc.dg/compat/vector-1_x.c: Add 32byte vector tests. + * gcc.dg/compat/vector-1_y.c: Likewise. + * gcc.dg/compat/vector-2_x.c: Likewise. + * gcc.dg/compat/vector-2_y.c: Likewise. + + * gcc.dg/compat/vector-1a_main.c: New. + * gcc.dg/compat/vector-1a_x.c: Likewise. + * gcc.dg/compat/vector-1a_y.c: Likewise. + * gcc.dg/compat/vector-2a_main.c: Likewise. + * gcc.dg/compat/vector-2a_x.c: Likewise. + * gcc.dg/compat/vector-2a_y.c: Likewise. + + * gcc.dg/compat/vector-defs.h (v32qi): New. + (v16hi): Likewise. + (v8si): Likewise. + (v4di): Likewise. + (v8sf): Likewise. + (v4df): Likewise. + (u32qi): Likewise. + (u16hi): Likewise. + (u8si): Likewise. + (u4di): Likewise. + (u8sf): Likewise. + (u4df): Likewise. + + * lib/compat.exp (compat-get-options-main): Support dg-skip-if. + +2008-07-07 Andy Hutchinson <hutchinsonandy@aim.com> + + * gcc.c-torture/compile/20080625-1.c: Skip for AVR target. + * gcc.dg/torture/pr36373-10.c: Correct test where target pointer + is not same size as unsigned long. + +2008-07-07 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/36670 + * gfortran.dg/product_sum_bounds_1.f90: New test case. + +2008-07-07 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/36341 + PR fortran/34670 + * gfortran.dg/matmul_bounds_2.f90: New test. + * gfortran.dg/matmul_bounds_3.f90: New test. + * gfortran.dg/matmul_bounds_4.f90: New test. + * gfortran.dg/matmul_bounds_5.f90: New test. + +2008-07-07 Richard Guenther <rguenther@suse.de> + + * gcc.dg/torture/pta-ptrarith-1.c: New testcase. + * gcc.dg/torture/pta-ptrarith-2.c: Likewise. + * gcc.dg/torture/ipa-pta-1.c: Likewise. + +2008-07-07 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/36726 + * gfortran.dg/gomp/pr36726.f90: New test. + +2008-07-06 Richard Sandiford <rdsandiford@googlemail.com> + + * gcc.target/mips/gcc-have-sync-compare-and-swap-1.c: Expect the + macros to be defined for MIPS16 too. + * gcc.target/mips/gcc-have-sync-compare-and-swap-2.c: Likewise. + * gcc.target/mips/gcc-have-sync-compare-and-swap-3.c: New test. + * gcc.target/mips/gcc-have-sync-compare-and-swap-4.c: Likewise. + +2008-07-06 Richard Guenther <rguenther@suse.de> + + * gcc.dg/tree-ssa/pta-callused.c: Adjust testcase. + +2008-07-06 Kai Tietz <kai.tietz@onevision.com> + + * gcc.dg/callabi/callabi.h: New. + * gcc.dg/callabi/vaarg-1.c: New. + * gcc.dg/callabi/vaarg-2.c: New. + * gcc.dg/callabi/vaarg-3.c: New. + * gcc.dg/callabi/func-1.c: New. + +2008-07-05 Andrew Pinski <andrew_pinski@playstation.sony.com> + + * g++.dg/tree-ssa/ptrmemfield.C: New testcase. + +2008-07-05 Joseph Myers <joseph@codesourcery.com> + + * lib/gcc-dg.exp (remove-build-file): Remove files on remote host + as well as on build. + +2008-07-04 Richard Guenther <rguenther@suse.de> + + * gcc.dg/tree-ssa/pta-callused.c: New testcase. + +2008-07-04 Richard Sandiford <richard@codesourcery.com> + + * gcc.target/m68k/interrupt-2.c: New file. + * gcc.dg/tree-ssa/20040204-1.c: Don't XFAIL for m68k*-*-*. + +2008-07-03 H.J. Lu <hongjiu.lu@intel.com> + + * gcc.dg/compat/struct-by-value-17a_x.c: Remove duplicated code. + * gcc.dg/compat/struct-by-value-17a_y.c: Likewise. + +2008-07-03 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/loop_optimization3.adb: New test. + * gnat.dg/loop_optimization3_pkg.ad[sb]: New helper. + +2008-07-03 Uros Bizjak <ubizjak@gmail.com> + + PR target/36710 + * gcc.target/i386/float128-2.c: New test. + +2008-07-03 Michael Meissner <gnu@the-meissners.org> + + PR middle-end/35736 + * gcc.dg/pr35736.c: New file. + +2008-07-03 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> + + * gcc.dg/pr28243.c: Skip on SPU. + * gcc.dg/torture/pr25947-1.c: Likewise. + * gcc.dg/20030702-1.c: Likewise. + * g++.old-deja/g++.other/comdat5.C: Likewise. + * g++.old-deja/g++.other/local-alloc1.C: Likewise. + * g++.dg/opt/vt1.C: Likewise. + +2008-07-03 H.J. Lu <hongjiu.lu@intel.com> + + * gcc.dg/compat/struct-by-value-17a_main.c: Remove duplicated code. + +2008-07-03 H.J. Lu <hongjiu.lu@intel.com> + Uros Bizjak <ubizjak@gmail.com> + + * gcc.target/i386/float128-1.c: New. + +2008-07-03 Andrew Haley <aph@redhat.com> + + PR preprocessor/33305 + * gcc.dg/cpp/avoidpaste1.c: Use dg-options "-ansi" to avoid + "-pedantic". + * gcc.dg/cpp/avoidpaste2.c: Likewise + * gcc.dg/cpp/20000519-1.c: Likewise. + * g++.dg/ext/gnu-inline-global-reject.C: Likewise. + * gcc.dg/cpp/c99-empty-macro-args.c: New test. + * gcc.dg/cpp/c90-empty-macro-args.c: New test. + +2008-07-03 Richard Guenther <rguenther@suse.de> + + PR c++/36128 + * g++.dg/other/builtin1.C: New testcase. + +2008-07-02 Joseph Myers <joseph@codesourcery.com> + + * g++.dg/compat/struct-layout-1.exp: Compile generator on build system. + * gcc.dg/compat/struct-layout-1.exp: Likewise. + * objc.dg/gnu-encoding/gnu-encoding.exp: Likewise. + +2008-07-02 Andy Hutchinson <hutchinsonandy@aim.com> + + PR testsuite/36285 + * gcc.dg/compat/struct-by-value-16_x.c: Move some tests to new file + to reduce code size. + * gcc.dg/compat/struct-by-value-16_y.c: Ditto. + * gcc.dg/compat/struct-by-value-16a_main.c: New file. + * gcc.dg/compat/struct-by-value-16a_x.c: Ditto. + * gcc.dg/compat/struct-by-value-16a_y.c: Ditto. + * gcc.dg/compat/struct-by-value-17_x.c: Move some tests to new file + to reduce code size. + * gcc.dg/compat/struct-by-value-17_y.c: Ditto. + * gcc.dg/compat/struct-by-value-17a_main.c: New file. + * gcc.dg/compat/struct-by-value-17a_x.c: Ditto. + * gcc.dg/compat/struct-by-value-17a_y.c: Ditto. + * gcc.dg/compat/struct-by-value-18_x.c: Move some tests to new file + to reduce code size. + * gcc.dg/compat/struct-by-value-18_y.c: Ditto. + * gcc.dg/compat/struct-by-value-18a_main.c: New file. + * gcc.dg/compat/struct-by-value-18a_x.c: Ditto. + * gcc.dg/compat/struct-by-value-18a_y.c: Ditto. + + +2008-07-02 Andy Hutchinson <hutchinsonandy@aim.com> + + * gcc.dg/pr36227.c: Correct test for targets where long is + not the same size as pointer. + +2008-07-02 Kaz Kojima <kkojima@gcc.gnu.org> + + * g++.dg/cdce3.C: Test long double math functions for + large_long_double target only. Skip pow10 and exp10 + functions for *-*-darwin*. + +2008-07-02 Janus Weil <janus@gcc.gnu.org> + Tobias Burnus <burnus@net-b.de> + + PR fortran/32580 + * gfortran.dg/c_f_pointer_tests_3.f90: Updated. + * gfortran.dg/proc_decl_1.f90: Updated. + * gfortran.dg/proc_ptr_1.f90: New. + * gfortran.dg/proc_ptr_2.f90: New. + * gfortran.dg/proc_ptr_3.f90: New. + * gfortran.dg/proc_ptr_4.f90: New. + * gfortran.dg/proc_ptr_5.f90: New. + * gfortran.dg/proc_ptr_6.f90: New. + * gfortran.dg/proc_ptr_7.f90: New. + * gfortran.dg/proc_ptr_8.f90: New. + +2008-07-02 Joseph Myers <joseph@codesourcery.com> + + * gcc.target/arm/neon/polytypes.c: Use dg-message separately from + dg-error to match separate messages. + +2008-07-02 H.J. Lu <hongjiu.lu@intel.com> + + * g++.dg/abi/mangle24.C: Remove -mmmx. + * gcc.dg/const-float80-ped.c: Likewise. + * gcc.dg/const-float80.c: Likewise. + * gcc.dg/torture/fp-int-convert-float80.c: Likewise. + + * g++.dg/abi/mangle25.C: Enable x86. + * gcc.dg/const-float128-ped.c: Likewise. + * gcc.dg/const-float128.c: Likewise. + * gcc.dg/torture/fp-int-convert-float128.c: Likewise. + * gcc.target/i386/pr32191.c: Likewise. + * gcc.target/i386/pr32268.c: Likewise. + +2008-07-02 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> + + PR target/36698 + * gcc.c-torture/compile/20001226-1.c: XFAIL -O0 case on SPU. + + * gcc.dg/pr27095.c: Provide target-specific regexp for SPU. + +2008-07-02 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> + + * lib/compat.exp (compat-execute): Add -ffunction-sections + and -Wl,--auto-overlay when building for spu-*-elf*. + +2008-07-02 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> + + * gcc.dg/nrv3.c (S): Increase size of padding for SPU. + * g++.dg/opt/temp1.C (struct T): Likewise. + +2008-07-02 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> + + * gcc.c-torture/execute/20030222-1.x: New file. + * gcc.dg/tree-ssa/ssa-fre-3.c: Disable test on SPU. + * gcc.dg/lower-subreg-1.c: Likewise. + 2008-07-02 Ulrich Weigand <Ulrich.Weigand@de.ibm.com> SPU single-precision FP does not support subnormals: diff --git a/gcc/testsuite/g++.dg/abi/mangle24.C b/gcc/testsuite/g++.dg/abi/mangle24.C index 16aa2ea8e59..3a9f629d5bf 100644 --- a/gcc/testsuite/g++.dg/abi/mangle24.C +++ b/gcc/testsuite/g++.dg/abi/mangle24.C @@ -5,7 +5,6 @@ // Origin: Joseph Myers <joseph@codesourcery.com> // { dg-do compile { target i?86-*-* x86_64-*-* ia64-*-* } } */ // { dg-options "" } */ -// { dg-options "-mmmx" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ // { dg-final { scan-assembler "_Z1fe" { target i?86-*-* x86_64-*-* } } } */ // { dg-final { scan-assembler "_Z1fe" { target { ia64-*-* && { ! "ia64-*-hpux*" } } } } } */ // { dg-final { scan-assembler "_Z1fu9__float80" { target ia64-*-hpux* } } } */ diff --git a/gcc/testsuite/g++.dg/abi/mangle25.C b/gcc/testsuite/g++.dg/abi/mangle25.C index 75819a7bfaf..e00ba5c692d 100644 --- a/gcc/testsuite/g++.dg/abi/mangle25.C +++ b/gcc/testsuite/g++.dg/abi/mangle25.C @@ -4,7 +4,7 @@ // ia64-hpux where "long double" is "e" and __float128 is synonymous with // "long double". // Origin: Joseph Myers <joseph@codesourcery.com> -// { dg-do compile { target { ia64-*-* || { { i?86-*-* x86_64-*-*} && lp64 } } } } +// { dg-do compile { target ia64-*-* i?86-*-* x86_64-*-* } } // { dg-options "" } */ // { dg-final { scan-assembler "_Z1fg" { target i?86-*-* x86_64-*-* } } } */ // { dg-final { scan-assembler "_Z1fg" { target { ia64-*-* && { ! "ia64-*-hpux*" } } } } } */ diff --git a/gcc/testsuite/g++.dg/cdce3.C b/gcc/testsuite/g++.dg/cdce3.C index 6c6afc89027..19f7f0b295a 100644 --- a/gcc/testsuite/g++.dg/cdce3.C +++ b/gcc/testsuite/g++.dg/cdce3.C @@ -1,21 +1,23 @@ -/* { dg-do run { target { ! "*-*-darwin*" } } } */ -/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */ -/* { dg-final { scan-tree-dump "cdce3.C:68: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:69: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:70: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:71: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:72: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:73: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:74: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:75: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:76: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:77: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:78: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:79: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:80: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:81: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:82: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ -/* { dg-final { scan-tree-dump "cdce3.C:83: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-do run } */ +/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -DNO_GNU_EXTENSION -lm" { target "*-*-darwin*" } } */ +/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" { target { {! "*-*-darwin*" } && large_long_double } } }*/ +/* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -DNO_LONG_DOUBLE -lm" { target {! large_long_double } } } */ +/* { dg-final { scan-tree-dump "cdce3.C:89: note: function call is shrink-wrapped into error conditions\." "cdce" { target {! "*-*-darwin*" } } } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:90: note: function call is shrink-wrapped into error conditions\." "cdce" { target {! "*-*-darwin*" } } } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:92: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:93: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:94: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:95: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:96: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:97: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:98: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:99: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:100: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:101: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:102: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:103: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:104: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ +/* { dg-final { scan-tree-dump "cdce3.C:105: note: function call is shrink-wrapped into error conditions\." "cdce" } }*/ /* { dg-final { cleanup-tree-dump "cdce" } } */ #include <stdlib.h> #include <math.h> @@ -23,9 +25,24 @@ #include <stdio.h> #endif #include <errno.h> -typedef long double ldouble; typedef void (*FP) (int xp); #define NI __attribute__((noinline)) + +#if defined(NO_LONG_DOUBLE) +double result; + +#define DEF_MATH_FUNC(prefix, name) NI void prefix##name##f (int x) \ +{ \ + float yy = name##f ((float) x); \ + STORE_RESULT; \ +} \ +NI void prefix##name (int x) \ +{ \ + double yy = name ((double)x); \ + STORE_RESULT; \ +} +#else +typedef long double ldouble; ldouble result; #define DEF_MATH_FUNC(prefix, name) NI void prefix##name##f (int x) \ @@ -42,12 +59,15 @@ NI void prefix##name##l (int x) \ { \ ldouble yy = name##l ((ldouble)x); \ STORE_RESULT; \ -} +} +#endif #undef STORE_RESULT #define STORE_RESULT result = yy +#if !defined(NO_GNU_EXTENSION) DEF_MATH_FUNC (m,pow10) DEF_MATH_FUNC (m,exp10) +#endif DEF_MATH_FUNC (m,exp2) DEF_MATH_FUNC (m,exp) DEF_MATH_FUNC (m,expm1) @@ -65,8 +85,10 @@ DEF_MATH_FUNC (m,sqrt) #undef STORE_RESULT #define STORE_RESULT +#if !defined(NO_GNU_EXTENSION) DEF_MATH_FUNC (o,pow10) DEF_MATH_FUNC (o,exp10) +#endif DEF_MATH_FUNC (o,exp2) DEF_MATH_FUNC (o,exp) DEF_MATH_FUNC (o,expm1) @@ -82,9 +104,14 @@ DEF_MATH_FUNC (o,log10) DEF_MATH_FUNC (o,log1p) DEF_MATH_FUNC (o,sqrt) +#if defined(NO_LONG_DOUBLE) +#define INIT_MATH_FUNC(prefix, name, lb, ub) { prefix##name##f, #name "f", 0, 0, lb, ub }, \ +{ prefix##name, #name, 0, 0, lb, ub }, +#else #define INIT_MATH_FUNC(prefix, name, lb, ub) { prefix##name##f, #name "f", 0, 0, lb, ub }, \ { prefix##name, #name, 0, 0, lb, ub }, \ { prefix##name##l, #name "l" , 0, 0, lb, ub }, +#endif struct MathFuncInfo { @@ -95,8 +122,10 @@ struct MathFuncInfo bool has_lb; bool has_ub; } math_func_arr[] = { +#if !defined(NO_GNU_EXTENSION) INIT_MATH_FUNC (m,pow10, false, true) INIT_MATH_FUNC (m,exp10, false, true) +#endif INIT_MATH_FUNC (m,exp2, false, true) INIT_MATH_FUNC (m,expm1, false, true) INIT_MATH_FUNC (m,exp, false, true) @@ -114,8 +143,11 @@ struct MathFuncInfo { 0, 0, 0, 0, 0, 0} }; MathFuncInfo opt_math_func_arr[] = -{ INIT_MATH_FUNC (o,pow10, false, true) +{ +#if !defined(NO_GNU_EXTENSION) + INIT_MATH_FUNC (o,pow10, false, true) INIT_MATH_FUNC (o,exp10, false, true) +#endif INIT_MATH_FUNC (o,exp2, false, true) INIT_MATH_FUNC (o,expm1, false, true) INIT_MATH_FUNC (o,exp, false, true) diff --git a/gcc/testsuite/g++.dg/compat/struct-layout-1.exp b/gcc/testsuite/g++.dg/compat/struct-layout-1.exp index 14473486aeb..cd58e7302a2 100644 --- a/gcc/testsuite/g++.dg/compat/struct-layout-1.exp +++ b/gcc/testsuite/g++.dg/compat/struct-layout-1.exp @@ -136,7 +136,7 @@ if [info exists env(GCC_EXEC_PREFIX)] { set orig_gcc_exec_prefix_saved 1 unsetenv GCC_EXEC_PREFIX } -set status [remote_exec host "$HOSTCC $HOSTCFLAGS $generator_cmd"] +set status [remote_exec build "$HOSTCC $HOSTCFLAGS $generator_cmd"] set status [lindex $status 0] if { $orig_gcc_exec_prefix_saved } { set orig_gcc_exec_prefix_saved 0 diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist1.C b/gcc/testsuite/g++.dg/cpp0x/initlist1.C new file mode 100644 index 00000000000..b7583da7829 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist1.C @@ -0,0 +1,69 @@ +// Basic uses of initializer lists +// { dg-do run } +// { dg-options "-std=c++0x" } + +#include <initializer_list> + +extern "C" void abort(); + +using namespace std; + +struct A { int i,j; A(int _i,int _j): i(_i), j(_j) {} }; +struct B { A a; B(A _a): a(_a) {} }; +struct C { B b; C(B _b): b(_b) {} }; + +struct D +{ + int ia[3]; + D (initializer_list<int> l) + { + const int *p = l.begin(); + for (int i = 0; i < 3; ++i) + ia[i] = *p++; + } +}; + +void f(C c) +{ + if (c.b.a.i != 1) abort(); + if (c.b.a.j != 2) abort(); +} +void f(int); + +void g(D d) +{ + if (d.ia[0] != 1 || d.ia[1] != 2 || d.ia[2] != 3) + abort(); +} + +struct E +{ + int i, j, k; +}; + +void h(E e) +{ + if (e.i != 1 || e.j != 2 || e.k != 3) + abort(); +} + +void i(initializer_list<int> l) +{ + const int *p = l.begin(); + if (*p++ != 1) abort(); + if (*p++ != 2) abort(); + if (*p++ != 3) abort(); + if (p != l.end()) abort(); +} + +int main() +{ + g({1,2,3}); + + h({1,2,3}); + + f({{{1,2}}}); + f({{A{1,2}}}); + + i({1,2,3}); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist2.C b/gcc/testsuite/g++.dg/cpp0x/initlist2.C new file mode 100644 index 00000000000..2fe4770560d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist2.C @@ -0,0 +1,32 @@ +// Test that conversion to std::initializer_list takes priority over other +// user-defined conversions. + +// { dg-do link } +// { dg-options "-std=c++0x" } + +#include <initializer_list> + +struct string +{ + string (const char *) {} + template <class Iter> string (Iter, Iter); +}; + +template <class T, class U> +struct pair +{ + pair (T t, U u) {} +}; + +template<class T, class U> +struct map +{ + void insert (pair<T,U>); + void insert (std::initializer_list<pair<T,U> >) {} +}; + +int main() +{ + map<string,string> m; + m.insert({ {"this","that"}, {"me","you"} }); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist3.C b/gcc/testsuite/g++.dg/cpp0x/initlist3.C new file mode 100644 index 00000000000..412deb51129 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist3.C @@ -0,0 +1,11 @@ +// { dg-options "-std=c++0x" } + +#include <initializer_list> + +template <class T> void f(std::initializer_list<T>); + +void g() +{ + f({1,2,3}); +} + diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist4.C b/gcc/testsuite/g++.dg/cpp0x/initlist4.C new file mode 100644 index 00000000000..d1ffab8546c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist4.C @@ -0,0 +1,32 @@ +// Test for initializer-list 'explicit' rule +// { dg-options "-std=c++0x" } + +struct A +{ + explicit A(int,int); + operator bool(); +}; + +A f(A) +{ + A{1,2}; + A a1{1,2}; + new A{1,2}; + if (A a5{1,2}); + + A({1,2}); // { dg-error "explicit" } + A a2({1,2}); // { dg-error "explicit" } + A a3 = {1,2}; // { dg-error "explicit" } + new A({1,2}); // { dg-error "explicit" } + f({1,2}); // { dg-error "explicit" } + a1 = {1,2}; // { dg-error "explicit" } + if (A a4 = {1,2}); // { dg-error "explicit" } + return {1,2}; // { dg-error "explicit" } +} + +struct B +{ + A a; + B(): a{1,2} {} + B(const B&): a({1,2}) {} // { dg-error "explicit" } +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist5.C b/gcc/testsuite/g++.dg/cpp0x/initlist5.C new file mode 100644 index 00000000000..0d02fd42d7f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist5.C @@ -0,0 +1,21 @@ +// Test for narrowing diagnostics +// { dg-options "-std=c++0x" } + +#include <initializer_list> + +struct A { int i; int j; }; +A a2 { 1.2 }; // { dg-error "narrowing" } +A a1 { 1, 2 }; // aggregate initialization +struct B { + B(std::initializer_list<int>); +}; +B b1 { 1, 2 }; // creates initializer_list<int> and calls constructor +B b2 { 1, 2.0 }; // { dg-error "narrowing" } +struct C { + C(int i, double j); +}; +C c1 = { 1, 2.2 }; // calls constructor with arguments (1, 2.2) +C c2 = { 1.1, 2 }; // { dg-error "narrowing" } + +int j { 1 }; // initialize to 1 +int k {}; // initialize to 0 diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist6.C b/gcc/testsuite/g++.dg/cpp0x/initlist6.C new file mode 100644 index 00000000000..523570315eb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist6.C @@ -0,0 +1,30 @@ +// Test for initlist lifetime +// { dg-options "-std=c++0x" } +// { dg-do run } + +#include <initializer_list> + +int c; + +struct A +{ + A(int,int) { ++c; } + ~A() { --c; } +}; + +void f (std::initializer_list<A> l) { } + +int main() +{ + f({ {1,2}, {3,4} }); + if (c != 0) + return 1; + + { + std::initializer_list<A> l { {1,2}, {3,4} }; + if (c != 2) + return 2; + } + if (c != 0) + return 3; +} diff --git a/gcc/testsuite/g++.dg/ext/gnu-inline-global-reject.C b/gcc/testsuite/g++.dg/ext/gnu-inline-global-reject.C index 2f2b8f29a08..d9e26609550 100644 --- a/gcc/testsuite/g++.dg/ext/gnu-inline-global-reject.C +++ b/gcc/testsuite/g++.dg/ext/gnu-inline-global-reject.C @@ -4,6 +4,7 @@ */ /* { dg-do compile } */ +/* { dg-options " -ansi -Wno-long-long" } */ #include "gnu-inline-common.h" diff --git a/gcc/testsuite/g++.dg/inherit/error4.C b/gcc/testsuite/g++.dg/inherit/error4.C index 77fa75d1994..d56d67f7556 100644 --- a/gcc/testsuite/g++.dg/inherit/error4.C +++ b/gcc/testsuite/g++.dg/inherit/error4.C @@ -2,9 +2,9 @@ struct A { virtual ~A(); }; -struct B : A A {}; // { dg-error "'A'|function definition|extra" } +struct B : A A {}; // { dg-error "" } -A foo(const B &b) +A foo(const B &b) // { dg-error "" } { - return b; // { dg-error "conversion" } + return b; } diff --git a/gcc/testsuite/g++.dg/init/brace2.C b/gcc/testsuite/g++.dg/init/brace2.C index 2af063d5f56..619a20f3c70 100644 --- a/gcc/testsuite/g++.dg/init/brace2.C +++ b/gcc/testsuite/g++.dg/init/brace2.C @@ -5,4 +5,4 @@ const char * y = { "hello" }; int a = 2; int b = { 2,3 }; // { dg-error "requires one element in initializer" } int c = { { 2 } } ; // { dg-error "braces around scalar initializer" } -int d = {}; // { dg-error "requires one element in initializer" } +int d = {}; // { dg-error "initializer" } diff --git a/gcc/testsuite/g++.dg/init/brace6.C b/gcc/testsuite/g++.dg/init/brace6.C index ffb70118f9e..066d1ba65ff 100644 --- a/gcc/testsuite/g++.dg/init/brace6.C +++ b/gcc/testsuite/g++.dg/init/brace6.C @@ -6,7 +6,7 @@ struct A { }; struct B { - B(const B&); + B(const B&); // { dg-error "candidate" } int b; }; @@ -18,8 +18,8 @@ int main() { int i = { 1 }; int j = { 1, 2 }; /* { dg-error "requires one element" } */ - A a = { 6 }; /* { dg-error "initializer for non" } */ - B b = { 6 }; /* { dg-error "initializer for non" } */ + A a = { 6 }; /* { dg-error "initialize" } */ + B b = { 6 }; /* { dg-error "initialize" } */ C c = { 6 }; /* { dg-error "too many initializers" } */ D d = { 6 }; } diff --git a/gcc/testsuite/g++.dg/opt/temp1.C b/gcc/testsuite/g++.dg/opt/temp1.C index b822dc464fe..dc13f516246 100644 --- a/gcc/testsuite/g++.dg/opt/temp1.C +++ b/gcc/testsuite/g++.dg/opt/temp1.C @@ -24,7 +24,12 @@ void *memcpy (void *dest, const void *src, __SIZE_TYPE__ n) } struct T { +#ifdef __SPU__ + /* SPU returns aggregates up to 1172 bytes in registers. */ + int a[300]; +#else int a[128]; +#endif T &operator+=(T const &v) __attribute__((noinline)); T operator+(T const &v) const { T t = *this; t += v; return t; } }; diff --git a/gcc/testsuite/g++.dg/opt/vt1.C b/gcc/testsuite/g++.dg/opt/vt1.C index b3abb5d57a2..ea74f52126f 100644 --- a/gcc/testsuite/g++.dg/opt/vt1.C +++ b/gcc/testsuite/g++.dg/opt/vt1.C @@ -1,6 +1,7 @@ // Test whether vtable for S is not put into read-only section. // { dg-do compile { target fpic } } // { dg-options "-O2 -fpic -fno-rtti" } +// { dg-skip-if "requires unsupported run-time relocation" { spu-*-* } { "*" } { "" } } // Origin: Jakub Jelinek <jakub@redhat.com> struct S diff --git a/gcc/testsuite/g++.dg/other/builtin1.C b/gcc/testsuite/g++.dg/other/builtin1.C new file mode 100644 index 00000000000..88665819987 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/builtin1.C @@ -0,0 +1,6 @@ +/* { dg-do compile } */ + +void foo() +{ + __builtin_isless (foo, 0); /* { dg-error "non-floating-point arguments" } */ +} diff --git a/gcc/testsuite/g++.dg/parse/crash36.C b/gcc/testsuite/g++.dg/parse/crash36.C index bcd96e4ec1f..1397e87d256 100644 --- a/gcc/testsuite/g++.dg/parse/crash36.C +++ b/gcc/testsuite/g++.dg/parse/crash36.C @@ -2,7 +2,7 @@ // { dg-do compile } // { dg-options "-std=c++98" } -template <typename... T> struct A // { dg-error "does not include variadic templates" } +template <typename... T> struct A // { dg-error "variadic templates" } { static T &t; // { dg-error "not expanded with|T" } static const int i = sizeof (++t); // { dg-error "was not declared in this scope" } diff --git a/gcc/testsuite/g++.dg/parse/ctor3.C b/gcc/testsuite/g++.dg/parse/ctor3.C index 193ffae24fe..e597d926f40 100644 --- a/gcc/testsuite/g++.dg/parse/ctor3.C +++ b/gcc/testsuite/g++.dg/parse/ctor3.C @@ -4,5 +4,5 @@ struct A {}; struct B : A { - B() : A {} // { dg-error "expected" } + B() : A {} // { dg-error "initializer|expected" } }; diff --git a/gcc/testsuite/g++.dg/tree-ssa/ptrmemfield.C b/gcc/testsuite/g++.dg/tree-ssa/ptrmemfield.C new file mode 100644 index 00000000000..38189eb43af --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/ptrmemfield.C @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +// { dg-options "-O2 -fdump-tree-final_cleanup" } + + +struct f +{ + char m; + char m1; +}; + +static inline char f:: *g(int a) +{ + return a?0:&f::m; +} + +int h(void) +{ + char f:: *a = g(0); + return a == 0; +} + +/* We should have no cast to offset_type. */ +/* { dg-final { scan-tree-dump-times "offset_type" 0 "final_cleanup"} } */ +// And we should optimized this code to just return 0 +/* { dg-final { scan-tree-dump-times "return 0" 1 "final_cleanup"} } */ +/* { dg-final { cleanup-tree-dump "final_cleanup" } } */ + diff --git a/gcc/testsuite/g++.old-deja/g++.other/comdat5.C b/gcc/testsuite/g++.old-deja/g++.other/comdat5.C index 5c2baa389e2..ad707f57247 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/comdat5.C +++ b/gcc/testsuite/g++.old-deja/g++.other/comdat5.C @@ -2,5 +2,6 @@ // { dg-do link { target fpic } } // { dg-additional-sources " comdat5-aux.cc" } // { dg-options "-O2 -fPIC" } +// { dg-skip-if "requires unsupported run-time relocation" { spu-*-* } { "*" } { "" } } #include "comdat4.C" diff --git a/gcc/testsuite/g++.old-deja/g++.other/local-alloc1.C b/gcc/testsuite/g++.old-deja/g++.other/local-alloc1.C index fe9d24fccf7..7488f1971c4 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/local-alloc1.C +++ b/gcc/testsuite/g++.old-deja/g++.other/local-alloc1.C @@ -1,5 +1,6 @@ // { dg-do assemble { target fpic } } // { dg-options "-O0 -fpic" } +// { dg-skip-if "requires unsupported run-time relocation" { spu-*-* } { "*" } { "" } } // Origin: Jakub Jelinek <jakub@redhat.com> struct bar { diff --git a/gcc/testsuite/gcc.c-torture/compile/20001226-1.c b/gcc/testsuite/gcc.c-torture/compile/20001226-1.c index cfcf546e157..19701ab3877 100644 --- a/gcc/testsuite/gcc.c-torture/compile/20001226-1.c +++ b/gcc/testsuite/gcc.c-torture/compile/20001226-1.c @@ -4,6 +4,7 @@ /* { dg-xfail-if "function larger than 64K" { m6811-*-* } { "*" } { "" } } */ /* { dg-skip-if "too much code for avr" { "avr-*-*" } { "*" } { "" } } */ /* { dg-xfail-if "jump beyond 128K not supported" { xtensa-*-* } { "-O0" } { "" } } */ +/* { dg-xfail-if "PR36698" { spu-*-* } { "-O0" } { "" } } */ /* { dg-skip-if "" { m32c-*-* } { "*" } { "" } } */ /* This testcase exposed two branch shortening bugs on powerpc. */ diff --git a/gcc/testsuite/gcc.c-torture/compile/20080625-1.c b/gcc/testsuite/gcc.c-torture/compile/20080625-1.c index f0900fd9693..226bea1ffae 100644 --- a/gcc/testsuite/gcc.c-torture/compile/20080625-1.c +++ b/gcc/testsuite/gcc.c-torture/compile/20080625-1.c @@ -1,3 +1,4 @@ +/* { dg-skip-if "too much data" { "avr-*-*" } { "*" } { "" } } */ struct peakbufStruct { unsigned int lnum [5000]; int lscan [5000][4000]; diff --git a/gcc/testsuite/gcc.c-torture/execute/20030222-1.x b/gcc/testsuite/gcc.c-torture/execute/20030222-1.x new file mode 100644 index 00000000000..e195563ddd0 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20030222-1.x @@ -0,0 +1,6 @@ +if [istarget "spu-*-*"] { + # Using inline assembly to convert long long to int is not working quite + # right # on the SPU. An extra shift-left-4-byte is needed. + return 1 +} +return 0 diff --git a/gcc/testsuite/gcc.dg/20030702-1.c b/gcc/testsuite/gcc.dg/20030702-1.c index 892f7d50539..4dbb4c50fc5 100644 --- a/gcc/testsuite/gcc.dg/20030702-1.c +++ b/gcc/testsuite/gcc.dg/20030702-1.c @@ -2,6 +2,7 @@ correctly in combine. */ /* { dg-do compile { target fpic } } */ /* { dg-options "-O2 -fpic -fprofile-arcs" } */ +/* { dg-skip-if "requires unsupported run-time relocation" { spu-*-* } { "*" } { "" } } */ void test (void) { diff --git a/gcc/testsuite/gcc.dg/callabi/callabi.h b/gcc/testsuite/gcc.dg/callabi/callabi.h new file mode 100644 index 00000000000..d008ad659cb --- /dev/null +++ b/gcc/testsuite/gcc.dg/callabi/callabi.h @@ -0,0 +1,50 @@ +/* First the default target definition. */ +#ifndef __GNUC_VA_LIST +#define __GNUC_VA_LIST + typedef __builtin_va_list __gnuc_va_list; +#endif + +#ifndef _VA_LIST_DEFINED +#define _VA_LIST_DEFINED + typedef __gnuc_va_list va_list; +#endif + +#define __va_copy(d,s) __builtin_va_copy(d,s) +#define __va_start(v,l) __builtin_va_start(v,l) +#define __va_arg(v,l) __builtin_va_arg(v,l) +#define __va_end(v) __builtin_va_end(v) + +#define __ms_va_copy(d,s) __builtin_ms_va_copy(d,s) +#define __ms_va_start(v,l) __builtin_ms_va_start(v,l) +#define __ms_va_arg(v,l) __builtin_va_arg(v,l) +#define __ms_va_end(v) __builtin_ms_va_end(v) + +#define __sysv_va_copy(d,s) __builtin_sysv_va_copy(d,s) +#define __sysv_va_start(v,l) __builtin_sysv_va_start(v,l) +#define __sysv_va_arg(v,l) __builtin_va_arg(v,l) +#define __sysv_va_end(v) __builtin_sysv_va_end(v) + +#define CALLABI_NATIVE + +#ifdef _WIN64 +#define CALLABI_CROSS __attribute__ ((sysv_abi)) + +#define CROSS_VA_LIST __builtin_sysv_va_list + +#define CROSS_VA_COPY(d,s) __sysv_va_copy(d,s) +#define CROSS_VA_START(v,l) __sysv_va_start(v,l) +#define CROSS_VA_ARG(v,l) __sysv_va_arg(v,l) +#define CROSS_VA_END(v) __sysv_va_end(v) + +#else + +#define CALLABI_CROSS __attribute__ ((ms_abi)) + +#define CROSS_VA_LIST __builtin_ms_va_list + +#define CROSS_VA_COPY(d,s) __ms_va_copy(d,s) +#define CROSS_VA_START(v,l) __ms_va_start(v,l) +#define CROSS_VA_ARG(v,l) __ms_va_arg(v,l) +#define CROSS_VA_END(v) __ms_va_end(v) + +#endif
\ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/callabi/func-1.c b/gcc/testsuite/gcc.dg/callabi/func-1.c new file mode 100644 index 00000000000..c727dbe6e53 --- /dev/null +++ b/gcc/testsuite/gcc.dg/callabi/func-1.c @@ -0,0 +1,40 @@ +/* Test for cross x86_64<->w64 abi standard calls. +*/ +/* Origin: Kai Tietz <kai.tietz@onevision.com> */ +/* { dg-do run { target { x86_64-*-* } } } */ +/* { dg-options "-std=gnu99 -ffast-math" } */ +#include "callabi.h" + +extern void abort (void); + +long double +CALLABI_CROSS func_cross (long double a, double b, float c, long d, int e, + char f) +{ + long double ret; + ret = a + (long double) b + (long double) c; + ret *= (long double) (d + (long) e); + if (f>0) + ret += func_cross (a,b,c,d,e,-f); + return ret; +} + +long double +CALLABI_NATIVE func_native (long double a, double b, float c, long d, int e, + char f) +{ + long double ret; + ret = a + (long double) b + (long double) c; + ret *= (long double) (d + (long) e); + if (f>0) + ret += func_native (a,b,c,d,e,-f); + return ret; +} + +int main () +{ + if (func_cross (1.0,2.0,3.0,1,2,3) + != func_native (1.0,2.0,3.0,1,2,3)) + abort (); + return 0; +}
\ No newline at end of file diff --git a/gcc/testsuite/gcc.dg/callabi/vaarg-1.c b/gcc/testsuite/gcc.dg/callabi/vaarg-1.c new file mode 100644 index 00000000000..1e745e56085 --- /dev/null +++ b/gcc/testsuite/gcc.dg/callabi/vaarg-1.c @@ -0,0 +1,47 @@ +/* Test for cross x86_64<->w64 abi va_list calls. +*/ +/* Origin: Kai Tietz <kai.tietz@onevision.com> */ +/* { dg-do run { target { x86_64-*-* } } } */ +/* { dg-options "-std=gnu99" } */ +#include "callabi.h" + +extern __SIZE_TYPE__ strlen (const char *); +extern int sprintf (char *,const char *, ...); +extern void abort (void); + +static +void CALLABI_CROSS vdo_cpy (char *s, CROSS_VA_LIST argp) +{ + __SIZE_TYPE__ len; + char *r = s; + char *e; + *r = 0; + for (;;) { + e = CROSS_VA_ARG (argp,char *); + if (*e == 0) break; + sprintf (r,"%s", e); + r += strlen (r); + } +} + +static +void CALLABI_CROSS do_cpy (char *s, ...) +{ + CROSS_VA_LIST argp; + CROSS_VA_START (argp, s); + vdo_cpy (s, argp); + CROSS_VA_END (argp); +} + +int main () +{ + char s[256]; + + do_cpy (s, "1","2","3","4", "5", "6", "7", ""); + + if (s[0] != '1' || s[1] !='2' || s[2] != '3' || s[3] != '4' + || s[4] != '5' || s[5] != '6' || s[6] != '7' || s[7] != 0) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/callabi/vaarg-2.c b/gcc/testsuite/gcc.dg/callabi/vaarg-2.c new file mode 100644 index 00000000000..c9b716194a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/callabi/vaarg-2.c @@ -0,0 +1,47 @@ +/* Test for cross x86_64<->w64 abi va_list calls. +*/ +/* Origin: Kai Tietz <kai.tietz@onevision.com> */ +/* { dg-do run { target { x86_64-*-* } } } */ +/* { dg-options "-std=gnu99" } */ +#include "callabi.h" + +extern void abort (void); + +#define SZ_ARGS 1ll,2ll,3ll,4ll,5ll,6ll,7ll,0ll + +static +int CALLABI_CROSS fct1 (va_list argp, ...) +{ + long long p1,p2; + int ret = 1; + CROSS_VA_LIST argp_2; + CROSS_VA_START (argp_2,argp); + + do { + p1 = CROSS_VA_ARG (argp_2, long long); + p2 = __va_arg (argp, long long); + if (p1 != p2) + ret = 0; + } while (ret && p1 != 0); + CROSS_VA_END (argp_2); + return ret; +} + +static +int fct2 (int dummy, ...) +{ + va_list argp; + int ret = dummy; + + __va_start (argp, dummy); + ret += fct1 (argp, SZ_ARGS); + __va_end (argp); + return ret; +} + +int main() +{ + if (fct2 (-1, SZ_ARGS) != 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/callabi/vaarg-3.c b/gcc/testsuite/gcc.dg/callabi/vaarg-3.c new file mode 100644 index 00000000000..d0d068754e1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/callabi/vaarg-3.c @@ -0,0 +1,47 @@ +/* Test for cross x86_64<->w64 abi va_list calls. +*/ +/* Origin: Kai Tietz <kai.tietz@onevision.com> */ +/* { dg-do run { target { x86_64-*-* } } } */ +/* { dg-options "-std=gnu99" } */ +#include "callabi.h" + +extern void abort (void); + +#define SZ_ARGS 1ll,2ll,3ll,4ll,5ll,6ll,7ll,0ll + +static +int fct1 (CROSS_VA_LIST argp, ...) +{ + long long p1,p2; + int ret = 1; + va_list argp_2; + + __va_start (argp_2,argp); + do { + p1 = __va_arg (argp_2, long long); + p2 = CROSS_VA_ARG (argp, long long); + if (p1 != p2) + ret = 0; + } while (ret && p1 != 0); + __va_end (argp_2); + return ret; +} + +static +int CALLABI_CROSS fct2 (int dummy, ...) +{ + CROSS_VA_LIST argp; + int ret = dummy; + + CROSS_VA_START (argp, dummy); + ret += fct1 (argp, SZ_ARGS); + CROSS_VA_END (argp); + return ret; +} + +int main() +{ + if (fct2 (-1, SZ_ARGS) != 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-16_x.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-16_x.c index 6b7331833ae..eb995921467 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-by-value-16_x.c +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-16_x.c @@ -19,10 +19,7 @@ TEST(Scf9, _Complex float) TEST(Scf10, _Complex float) TEST(Scf11, _Complex float) TEST(Scf12, _Complex float) -TEST(Scf13, _Complex float) -TEST(Scf14, _Complex float) -TEST(Scf15, _Complex float) -TEST(Scf16, _Complex float) + #undef T @@ -45,10 +42,7 @@ T(Scf9, _Complex float) T(Scf10, _Complex float) T(Scf11, _Complex float) T(Scf12, _Complex float) -T(Scf13, _Complex float) -T(Scf14, _Complex float) -T(Scf15, _Complex float) -T(Scf16, _Complex float) + DEBUG_FINI diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-16_y.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-16_y.c index 273d7cc4f3e..9450815e74c 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-by-value-16_y.c +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-16_y.c @@ -27,7 +27,4 @@ TEST(Scf9, _Complex float) TEST(Scf10, _Complex float) TEST(Scf11, _Complex float) TEST(Scf12, _Complex float) -TEST(Scf13, _Complex float) -TEST(Scf14, _Complex float) -TEST(Scf15, _Complex float) -TEST(Scf16, _Complex float) + diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-16a_main.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-16a_main.c new file mode 100644 index 00000000000..6a71d15b8ec --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-16a_main.c @@ -0,0 +1,14 @@ +/* Test structures passed by value, including to a function with a
+ variable-length argument lists. All struct members are of type
+ _Complex float. */
+
+extern void struct_by_value_16_x (void);
+extern void exit (int);
+int fails;
+
+int
+main ()
+{
+ struct_by_value_16a_x ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-16a_x.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-16a_x.c new file mode 100644 index 00000000000..0aa45249590 --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-16a_x.c @@ -0,0 +1,37 @@ +#include "compat-common.h"
+
+#include "fp-struct-defs.h"
+#include "fp-struct-check.h"
+#include "fp-struct-test-by-value-x.h"
+
+DEFS(cf, _Complex float)
+CHECKS(cf, _Complex float)
+
+
+TEST(Scf13, _Complex float)
+TEST(Scf14, _Complex float)
+TEST(Scf15, _Complex float)
+TEST(Scf16, _Complex float)
+
+#undef T
+
+void
+struct_by_value_16a_x ()
+{
+DEBUG_INIT
+
+#define T(TYPE, MTYPE) testit##TYPE ();
+
+
+T(Scf13, _Complex float)
+T(Scf14, _Complex float)
+T(Scf15, _Complex float)
+T(Scf16, _Complex float)
+
+DEBUG_FINI
+
+if (fails != 0)
+ abort ();
+
+#undef T
+}
diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-16a_y.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-16a_y.c new file mode 100644 index 00000000000..2fd561ef044 --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-16a_y.c @@ -0,0 +1,22 @@ +#include <stdarg.h>
+
+#include "compat-common.h"
+
+#ifdef SKIP_VA
+const int test_va = 0;
+#else
+const int test_va = 1;
+#endif
+
+#include "fp-struct-defs.h"
+#include "fp-struct-init.h"
+#include "fp-struct-test-by-value-y.h"
+
+DEFS(cf,_Complex float)
+INITS(cf, _Complex float)
+
+
+TEST(Scf13, _Complex float)
+TEST(Scf14, _Complex float)
+TEST(Scf15, _Complex float)
+TEST(Scf16, _Complex float)
diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-17_x.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-17_x.c index cba628bcb5b..93fd788ea45 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-by-value-17_x.c +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-17_x.c @@ -19,10 +19,7 @@ TEST(Scd9, _Complex double) TEST(Scd10, _Complex double) TEST(Scd11, _Complex double) TEST(Scd12, _Complex double) -TEST(Scd13, _Complex double) -TEST(Scd14, _Complex double) -TEST(Scd15, _Complex double) -TEST(Scd16, _Complex double) + #undef T @@ -45,10 +42,7 @@ T(Scd9, _Complex double) T(Scd10, _Complex double) T(Scd11, _Complex double) T(Scd12, _Complex double) -T(Scd13, _Complex double) -T(Scd14, _Complex double) -T(Scd15, _Complex double) -T(Scd16, _Complex double) + DEBUG_FINI diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-17_y.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-17_y.c index a0342a37c0c..f8ac0a7c15e 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-by-value-17_y.c +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-17_y.c @@ -27,7 +27,4 @@ TEST(Scd9, _Complex double) TEST(Scd10, _Complex double) TEST(Scd11, _Complex double) TEST(Scd12, _Complex double) -TEST(Scd13, _Complex double) -TEST(Scd14, _Complex double) -TEST(Scd15, _Complex double) -TEST(Scd16, _Complex double) + diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-17a_main.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-17a_main.c new file mode 100644 index 00000000000..1db00215f2c --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-17a_main.c @@ -0,0 +1,14 @@ +/* Test structures passed by value, including to a function with a + variable-length argument lists. All struct members are of type + _Complex double. */ + +extern void struct_by_value_17_x (void); +extern void exit (int); +int fails; + +int +main () +{ + struct_by_value_17a_x (); + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-17a_x.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-17a_x.c new file mode 100644 index 00000000000..5b2f1d1d920 --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-17a_x.c @@ -0,0 +1,37 @@ +#include "compat-common.h" + +#include "fp-struct-defs.h" +#include "fp-struct-check.h" +#include "fp-struct-test-by-value-x.h" + +DEFS(cd, _Complex double) +CHECKS(cd, _Complex double) + + +TEST(Scd13, _Complex double) +TEST(Scd14, _Complex double) +TEST(Scd15, _Complex double) +TEST(Scd16, _Complex double) + +#undef T + +void +struct_by_value_17a_x () +{ +DEBUG_INIT + +#define T(TYPE, MTYPE) testit##TYPE (); + + +T(Scd13, _Complex double) +T(Scd14, _Complex double) +T(Scd15, _Complex double) +T(Scd16, _Complex double) + +DEBUG_FINI + +if (fails != 0) + abort (); + +#undef T +} diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-17a_y.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-17a_y.c new file mode 100644 index 00000000000..d785a999d58 --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-17a_y.c @@ -0,0 +1,22 @@ +#include <stdarg.h> + +#include "compat-common.h" + +#ifdef SKIP_VA +const int test_va = 0; +#else +const int test_va = 1; +#endif + +#include "fp-struct-defs.h" +#include "fp-struct-init.h" +#include "fp-struct-test-by-value-y.h" + +DEFS(cd,_Complex double) +INITS(cd, _Complex double) + + +TEST(Scd13, _Complex double) +TEST(Scd14, _Complex double) +TEST(Scd15, _Complex double) +TEST(Scd16, _Complex double) diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-18_x.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-18_x.c index e040ecc79a7..f9dd6aa0b72 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-by-value-18_x.c +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-18_x.c @@ -19,10 +19,7 @@ TEST(Scld9, _Complex long double) TEST(Scld10, _Complex long double) TEST(Scld11, _Complex long double) TEST(Scld12, _Complex long double) -TEST(Scld13, _Complex long double) -TEST(Scld14, _Complex long double) -TEST(Scld15, _Complex long double) -TEST(Scld16, _Complex long double) + #undef T @@ -45,10 +42,7 @@ T(Scld9, _Complex long double) T(Scld10, _Complex long double) T(Scld11, _Complex long double) T(Scld12, _Complex long double) -T(Scld13, _Complex long double) -T(Scld14, _Complex long double) -T(Scld15, _Complex long double) -T(Scld16, _Complex long double) + DEBUG_FINI diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-18_y.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-18_y.c index b69425a5f4e..8c732d58273 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-by-value-18_y.c +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-18_y.c @@ -27,7 +27,4 @@ TEST(Scld9, _Complex long double) TEST(Scld10, _Complex long double) TEST(Scld11, _Complex long double) TEST(Scld12, _Complex long double) -TEST(Scld13, _Complex long double) -TEST(Scld14, _Complex long double) -TEST(Scld15, _Complex long double) -TEST(Scld16, _Complex long double) + diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-18a_main.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-18a_main.c new file mode 100644 index 00000000000..5b9dfd983b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-18a_main.c @@ -0,0 +1,14 @@ +/* Test structures passed by value, including to a function with a
+ variable-length argument lists. All struct members are of type
+ _Complex long double. */
+
+extern void struct_by_value_18_x (void);
+extern void exit (int);
+int fails;
+
+int
+main ()
+{
+ struct_by_value_18a_x ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-18a_x.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-18a_x.c new file mode 100644 index 00000000000..72f5bbf5d44 --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-18a_x.c @@ -0,0 +1,37 @@ +#include "compat-common.h"
+
+#include "fp-struct-defs.h"
+#include "fp-struct-check.h"
+#include "fp-struct-test-by-value-x.h"
+
+DEFS(cld, _Complex long double)
+CHECKS(cld, _Complex long double)
+
+
+TEST(Scld13, _Complex long double)
+TEST(Scld14, _Complex long double)
+TEST(Scld15, _Complex long double)
+TEST(Scld16, _Complex long double)
+
+#undef T
+
+void
+struct_by_value_18a_x ()
+{
+DEBUG_INIT
+
+#define T(TYPE, MTYPE) testit##TYPE ();
+
+
+T(Scld13, _Complex long double)
+T(Scld14, _Complex long double)
+T(Scld15, _Complex long double)
+T(Scld16, _Complex long double)
+
+DEBUG_FINI
+
+if (fails != 0)
+ abort ();
+
+#undef T
+}
diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-18a_y.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-18a_y.c new file mode 100644 index 00000000000..545dcf8970f --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-18a_y.c @@ -0,0 +1,22 @@ +#include <stdarg.h>
+
+#include "compat-common.h"
+
+#ifdef SKIP_VA
+const int test_va = 0;
+#else
+const int test_va = 1;
+#endif
+
+#include "fp-struct-defs.h"
+#include "fp-struct-init.h"
+#include "fp-struct-test-by-value-y.h"
+
+DEFS(cld,_Complex long double)
+INITS(cld, _Complex long double)
+
+
+TEST(Scld13, _Complex long double)
+TEST(Scld14, _Complex long double)
+TEST(Scld15, _Complex long double)
+TEST(Scld16, _Complex long double)
diff --git a/gcc/testsuite/gcc.dg/compat/struct-layout-1.exp b/gcc/testsuite/gcc.dg/compat/struct-layout-1.exp index 5de2c1e2618..992b62cdc09 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-layout-1.exp +++ b/gcc/testsuite/gcc.dg/compat/struct-layout-1.exp @@ -98,7 +98,7 @@ if [info exists env(GCC_EXEC_PREFIX)] { set orig_gcc_exec_prefix_saved 1 unsetenv GCC_EXEC_PREFIX } -set status [remote_exec host "$HOSTCC $HOSTCFLAGS $generator_cmd"] +set status [remote_exec build "$HOSTCC $HOSTCFLAGS $generator_cmd"] set status [lindex $status 0] if { $orig_gcc_exec_prefix_saved } { set orig_gcc_exec_prefix_saved 0 diff --git a/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c b/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c index c53c3e8c2bd..f6a217e6f56 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c +++ b/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c @@ -186,30 +186,42 @@ struct types vector_types[] = { /* vector-defs.h typedefs */ { "v8qi", TYPE_OTHER, 0, 0 }, { "v16qi", TYPE_OTHER, 0, 0 }, +{ "v32qi", TYPE_OTHER, 0, 0 }, { "v2hi", TYPE_OTHER, 0, 0 }, { "v4hi", TYPE_OTHER, 0, 0 }, { "v8hi", TYPE_OTHER, 0, 0 }, +{ "v16hi", TYPE_OTHER, 0, 0 }, { "v2si", TYPE_OTHER, 0, 0 }, { "v4si", TYPE_OTHER, 0, 0 }, +{ "v8si", TYPE_OTHER, 0, 0 }, { "v1di", TYPE_OTHER, 0, 0 }, { "v2di", TYPE_OTHER, 0, 0 }, +{ "v4di", TYPE_OTHER, 0, 0 }, { "v2sf", TYPE_OTHER, 0, 0 }, { "v4sf", TYPE_OTHER, 0, 0 }, +{ "v8sf", TYPE_OTHER, 0, 0 }, { "v16sf", TYPE_OTHER, 0, 0 }, { "v2df", TYPE_OTHER, 0, 0 }, +{ "v4df", TYPE_OTHER, 0, 0 }, { "u8qi", TYPE_OTHER, 0, 0 }, { "u16qi", TYPE_OTHER, 0, 0 }, +{ "u32qi", TYPE_OTHER, 0, 0 }, { "u2hi", TYPE_OTHER, 0, 0 }, { "u4hi", TYPE_OTHER, 0, 0 }, { "u8hi", TYPE_OTHER, 0, 0 }, +{ "u16hi", TYPE_OTHER, 0, 0 }, { "u2si", TYPE_OTHER, 0, 0 }, { "u4si", TYPE_OTHER, 0, 0 }, +{ "u8si", TYPE_OTHER, 0, 0 }, { "u1di", TYPE_OTHER, 0, 0 }, { "u2di", TYPE_OTHER, 0, 0 }, +{ "u4di", TYPE_OTHER, 0, 0 }, { "u2sf", TYPE_OTHER, 0, 0 }, { "u4sf", TYPE_OTHER, 0, 0 }, +{ "u8sf", TYPE_OTHER, 0, 0 }, { "u16sf", TYPE_OTHER, 0, 0 }, { "u2df", TYPE_OTHER, 0, 0 }, +{ "u4df", TYPE_OTHER, 0, 0 }, { "__m64", TYPE_OTHER, 0, 0 }, { "__m128", TYPE_OTHER, 0, 0 } #define NVTYPES2 (sizeof (vector_types) / sizeof (vector_types[0])) diff --git a/gcc/testsuite/gcc.dg/compat/union-m128-1_main.c b/gcc/testsuite/gcc.dg/compat/union-m128-1_main.c index 69dd34dce57..11f872154eb 100644 --- a/gcc/testsuite/gcc.dg/compat/union-m128-1_main.c +++ b/gcc/testsuite/gcc.dg/compat/union-m128-1_main.c @@ -1,6 +1,8 @@ +/* { dg-skip-if "test SSE2 support" { ! { i?86-*-* x86_64-*-* } } } */ /* { dg-options "-O" } */ -#ifdef __x86_64__ +#include "cpuid.h" + /* Test function argument passing. PR target/15301. */ extern void union_m128_1_x (void); @@ -9,13 +11,14 @@ extern void exit (int); int main () { - union_m128_1_x (); + unsigned int eax, ebx, ecx, edx; + + if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) + return 0; + + /* Run SSE vector test only if host has SSE2 support. */ + if (edx & bit_SSE2) + union_m128_1_x (); + exit (0); } -#else -int -main () -{ - return 0; -} -#endif diff --git a/gcc/testsuite/gcc.dg/compat/union-m128-1_x.c b/gcc/testsuite/gcc.dg/compat/union-m128-1_x.c index 06a4ef5ffdb..1f92303d95b 100644 --- a/gcc/testsuite/gcc.dg/compat/union-m128-1_x.c +++ b/gcc/testsuite/gcc.dg/compat/union-m128-1_x.c @@ -1,6 +1,5 @@ -/* { dg-options "-O" } */ +/* { dg-options "-O -msse2" } */ -#ifdef __x86_64__ #include "union-m128-1.h" SS_union_mi128 un; @@ -23,7 +22,3 @@ union_m128_1_x () foo(un); foo(st); } -#else -int dummy_x; -#endif - diff --git a/gcc/testsuite/gcc.dg/compat/union-m128-1_y.c b/gcc/testsuite/gcc.dg/compat/union-m128-1_y.c index 2b6eb0a6ee8..be9d6e8f3d5 100644 --- a/gcc/testsuite/gcc.dg/compat/union-m128-1_y.c +++ b/gcc/testsuite/gcc.dg/compat/union-m128-1_y.c @@ -1,6 +1,5 @@ -/* { dg-options "-O" } */ +/* { dg-options "-O -msse2" } */ -#ifdef __x86_64__ #include <stdlib.h> #include "union-m128-1.h" @@ -26,7 +25,3 @@ foo (SS_struct_mi128 st) || x.u [1] != 0xfedcba9876543210LL) abort (); } -#else -int dummy_y; -#endif - diff --git a/gcc/testsuite/gcc.dg/compat/vector-1_x.c b/gcc/testsuite/gcc.dg/compat/vector-1_x.c index 11995b496e5..ab4f88bf48b 100644 --- a/gcc/testsuite/gcc.dg/compat/vector-1_x.c +++ b/gcc/testsuite/gcc.dg/compat/vector-1_x.c @@ -8,13 +8,17 @@ SETUP (8, qi); SETUP (16, qi); +SETUP (32, qi); SETUP (2, hi); SETUP (4, hi); SETUP (8, hi); +SETUP (16, hi); SETUP (2, si); SETUP (4, si); +SETUP (8, si); SETUP (1, di); SETUP (2, di); +SETUP (4, di); #endif @@ -26,13 +30,17 @@ vector_1_x (void) CHECK (8, qi); CHECK (16, qi); + CHECK (32, qi); CHECK (2, hi); CHECK (4, hi); CHECK (8, hi); + CHECK (16, hi); CHECK (2, si); CHECK (4, si); + CHECK (8, si); CHECK (1, di); CHECK (2, di); + CHECK (4, di); DEBUG_FINI diff --git a/gcc/testsuite/gcc.dg/compat/vector-1_y.c b/gcc/testsuite/gcc.dg/compat/vector-1_y.c index 1cec61734b4..5a09c0eadb6 100644 --- a/gcc/testsuite/gcc.dg/compat/vector-1_y.c +++ b/gcc/testsuite/gcc.dg/compat/vector-1_y.c @@ -8,12 +8,16 @@ TEST (8, qi, 101) TEST (16, qi, 101) +TEST (32, qi, 90) TEST (2, hi, 201) TEST (4, hi, 202) TEST (8, hi, 203) +TEST (16, hi, 203) TEST (2, si, 301) TEST (4, si, 302) +TEST (8, si, 303) TEST (1, di, 401) TEST (2, di, 402) +TEST (4, di, 403) #endif diff --git a/gcc/testsuite/gcc.dg/compat/vector-1a_main.c b/gcc/testsuite/gcc.dg/compat/vector-1a_main.c new file mode 100644 index 00000000000..76fb2915e1d --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/vector-1a_main.c @@ -0,0 +1,26 @@ +/* { dg-skip-if "test SSE2 vector" { ! { i?86-*-* x86_64-*-* } } } */ + +/* Test compatibility of vector types: layout between separately-compiled + modules, parameter passing, and function return. This test uses + vectors of integer values. */ + +#include "cpuid.h" + +extern void vector_1_x (void); +extern void exit (int); +int fails; + +int +main () +{ + unsigned int eax, ebx, ecx, edx; + + if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) + return 0; + + /* Run SSE vector test only if host has SSE2 support. */ + if (edx & bit_SSE2) + vector_1_x (); + + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/compat/vector-1a_x.c b/gcc/testsuite/gcc.dg/compat/vector-1a_x.c new file mode 100644 index 00000000000..aa0fa7f208c --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/vector-1a_x.c @@ -0,0 +1,3 @@ +/* { dg-options "-w -mno-mmx -msse2" } */ + +#include "vector-1_x.c" diff --git a/gcc/testsuite/gcc.dg/compat/vector-1a_y.c b/gcc/testsuite/gcc.dg/compat/vector-1a_y.c new file mode 100644 index 00000000000..2c88e198845 --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/vector-1a_y.c @@ -0,0 +1,3 @@ +/* { dg-options "-w -mno-mmx -msse2" } */ + +#include "vector-1_y.c" diff --git a/gcc/testsuite/gcc.dg/compat/vector-2_x.c b/gcc/testsuite/gcc.dg/compat/vector-2_x.c index de5f29c2688..d08c77fe3a0 100644 --- a/gcc/testsuite/gcc.dg/compat/vector-2_x.c +++ b/gcc/testsuite/gcc.dg/compat/vector-2_x.c @@ -10,7 +10,9 @@ SETUP (2, sf); SETUP (4, sf); SETUP (16, sf); +SETUP (8, sf); SETUP (2, df); +SETUP (4, df); #endif @@ -22,7 +24,9 @@ vector_2_x (void) CHECK (2, sf); CHECK (4, sf); + CHECK (8, sf); CHECK (16, sf); + CHECK (4, df); CHECK (2, df); DEBUG_FINI diff --git a/gcc/testsuite/gcc.dg/compat/vector-2_y.c b/gcc/testsuite/gcc.dg/compat/vector-2_y.c index 10d7a064532..fd5830c35b3 100644 --- a/gcc/testsuite/gcc.dg/compat/vector-2_y.c +++ b/gcc/testsuite/gcc.dg/compat/vector-2_y.c @@ -9,7 +9,9 @@ TEST (2, sf, 301.0) TEST (4, sf, 302.0) +TEST (8, sf, 303.0) TEST (16, sf, 304.0) TEST (2, df, 402.0) +TEST (4, df, 402.0) #endif diff --git a/gcc/testsuite/gcc.dg/compat/vector-2a_main.c b/gcc/testsuite/gcc.dg/compat/vector-2a_main.c new file mode 100644 index 00000000000..96c1111fddc --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/vector-2a_main.c @@ -0,0 +1,26 @@ +/* { dg-skip-if "test SSE2 support" { ! { i?86-*-* x86_64-*-* } } } */ + +/* Test compatibility of vector types: layout between separately-compiled + modules, parameter passing, and function return. This test uses + vectors of floating points values. */ + +#include "cpuid.h" + +extern void vector_2_x (void); +extern void exit (int); +int fails; + +int +main () +{ + unsigned int eax, ebx, ecx, edx; + + if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) + return 0; + + /* Run SSE vector test only if host has SSE2 support. */ + if (edx & bit_SSE2) + vector_2_x (); + + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/compat/vector-2a_x.c b/gcc/testsuite/gcc.dg/compat/vector-2a_x.c new file mode 100644 index 00000000000..fcfacec04e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/vector-2a_x.c @@ -0,0 +1,3 @@ +/* { dg-options "-w -mno-mmx -msse2" } */ + +#include "vector-2_x.c" diff --git a/gcc/testsuite/gcc.dg/compat/vector-2a_y.c b/gcc/testsuite/gcc.dg/compat/vector-2a_y.c new file mode 100644 index 00000000000..3797acb6a57 --- /dev/null +++ b/gcc/testsuite/gcc.dg/compat/vector-2a_y.c @@ -0,0 +1,3 @@ +/* { dg-options "-w -mno-mmx -msse2" } */ + +#include "vector-2_y.c" diff --git a/gcc/testsuite/gcc.dg/compat/vector-defs.h b/gcc/testsuite/gcc.dg/compat/vector-defs.h index 7574e28c53d..f2f050527ec 100644 --- a/gcc/testsuite/gcc.dg/compat/vector-defs.h +++ b/gcc/testsuite/gcc.dg/compat/vector-defs.h @@ -56,6 +56,20 @@ typedef float __attribute__((mode(V2DF))) v2df; #endif +typedef qi __attribute__((vector_size (32))) v32qi; +typedef hi __attribute__((vector_size (32))) v16hi; +typedef si __attribute__((vector_size (32))) v8si; +typedef di __attribute__((vector_size (32))) v4di; +typedef sf __attribute__((vector_size (32))) v8sf; +typedef df __attribute__((vector_size (32))) v4df; + +typedef union U32QI { v32qi v; qi a[32]; } u32qi; +typedef union U16HI { v16hi v; hi a[16]; } u16hi; +typedef union U8SI { v8si v; si a[8]; } u8si; +typedef union U4DI { v4di v; di a[4]; } u4di; +typedef union U8SF { v8sf v; sf a[8]; } u8sf; +typedef union U4DF { v4df v; df a[4]; } u4df; + typedef union U8QI { v8qi v; qi a[8]; } u8qi; typedef union U16QI { v16qi v; qi a[16]; } u16qi; diff --git a/gcc/testsuite/gcc.dg/const-float128-ped.c b/gcc/testsuite/gcc.dg/const-float128-ped.c index 86a630cf951..6a6b6223ce2 100644 --- a/gcc/testsuite/gcc.dg/const-float128-ped.c +++ b/gcc/testsuite/gcc.dg/const-float128-ped.c @@ -1,5 +1,5 @@ /* Test 'q' suffix with -pedantic on __float128 type constants. */ -/* { dg-do compile { target { ia64-*-* || { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-do compile { target ia64-*-* i?86-*-* x86_64-*-* } } */ /* { dg-options "-pedantic" } */ __float128 a = 123.456789q; /* { dg-warning "non-standard suffix on floating constant" } */ diff --git a/gcc/testsuite/gcc.dg/const-float128.c b/gcc/testsuite/gcc.dg/const-float128.c index 146e0c9c986..116e4597b44 100644 --- a/gcc/testsuite/gcc.dg/const-float128.c +++ b/gcc/testsuite/gcc.dg/const-float128.c @@ -1,5 +1,5 @@ /* Test 'q' and 'Q' suffixes on __float128 type constants. */ -/* { dg-do compile { target { ia64-*-* || { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-do compile { target ia64-*-* i?86-*-* x86_64-*-* } } */ /* { dg-options "" } */ __float128 a = 123.456789q; diff --git a/gcc/testsuite/gcc.dg/const-float80-ped.c b/gcc/testsuite/gcc.dg/const-float80-ped.c index 9cf047804a4..d1cf316dcad 100644 --- a/gcc/testsuite/gcc.dg/const-float80-ped.c +++ b/gcc/testsuite/gcc.dg/const-float80-ped.c @@ -1,6 +1,5 @@ /* Test 'w' suffix with -pedantic on __float80 type constants. */ /* { dg-do compile { target i?86-*-* x86_64-*-* ia64-*-* } } */ /* { dg-options "-pedantic" } */ -/* { dg-options "-mmmx -pedantic" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ __float80 a = 123.456789w; /* { dg-warning "non-standard suffix on floating constant" } */ diff --git a/gcc/testsuite/gcc.dg/const-float80.c b/gcc/testsuite/gcc.dg/const-float80.c index f2a836d3e64..8ec771f8f9c 100644 --- a/gcc/testsuite/gcc.dg/const-float80.c +++ b/gcc/testsuite/gcc.dg/const-float80.c @@ -1,7 +1,6 @@ /* Test 'w' and 'W' suffixes on __float80 type constants. */ /* { dg-do compile { target i?86-*-* x86_64-*-* ia64-*-* } } */ /* { dg-options "" } */ -/* { dg-options "-mmmx" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ __float80 a = 123.456789W; __float80 b = 123.456789w; diff --git a/gcc/testsuite/gcc.dg/cpp/20000519-1.c b/gcc/testsuite/gcc.dg/cpp/20000519-1.c index 82ab3a26861..7cd7daa3ad2 100644 --- a/gcc/testsuite/gcc.dg/cpp/20000519-1.c +++ b/gcc/testsuite/gcc.dg/cpp/20000519-1.c @@ -1,6 +1,7 @@ /* Regression test for preprocessor crash. Reported by Mathias Froehlich <frohlich@na.uni-tuebingen.de>. */ /* { dg-do preprocess } */ +/* { dg-options "-ansi" } */ #define foo #define __CAT__(a,b,c,d) a##b##c##d diff --git a/gcc/testsuite/gcc.dg/cpp/avoidpaste1.c b/gcc/testsuite/gcc.dg/cpp/avoidpaste1.c index d304a744155..3591f9c08ae 100644 --- a/gcc/testsuite/gcc.dg/cpp/avoidpaste1.c +++ b/gcc/testsuite/gcc.dg/cpp/avoidpaste1.c @@ -1,6 +1,7 @@ /* Copyright (C) 2001, 2003 Free Software Foundation, Inc. */ /* { dg-do preprocess } */ +/* { dg-options "-ansi" } */ /* This tests that we avoid accidental pasting only before and after macros and arguments, and not when the tokens are already pasted diff --git a/gcc/testsuite/gcc.dg/cpp/avoidpaste2.c b/gcc/testsuite/gcc.dg/cpp/avoidpaste2.c index 42b549c8d6c..dc5bbc7f270 100644 --- a/gcc/testsuite/gcc.dg/cpp/avoidpaste2.c +++ b/gcc/testsuite/gcc.dg/cpp/avoidpaste2.c @@ -1,6 +1,7 @@ /* Copyright (C) 2001, 2003 Free Software Foundation, Inc. */ /* { dg-do preprocess } */ +/* { dg-options "-ansi" } */ /* This tests that we avoid accidental pasting, as well as gratuitous space insertion, in various nasty places _inside_ a macro's diff --git a/gcc/testsuite/gcc.dg/cpp/c90-empty-macro-args.c b/gcc/testsuite/gcc.dg/cpp/c90-empty-macro-args.c new file mode 100644 index 00000000000..e90f8e6cb69 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/c90-empty-macro-args.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c89 -pedantic" } */ + +#define f(a,b) f2(a,,b) +#define f2(a,b,c) a; b; c; +#define f3(a) a + +#define g() p() + +void p(void) {} + + +void foo(void) +{ + f(p(),p()); /* { dg-warning "macro f2 argument 2: empty macro arguments are undefined" } */ + f2(p(),,p()); /* { dg-warning "macro f2 argument 2: empty macro arguments are undefined" } */ + f3(); /* { dg-warning "macro f3 argument 1: empty macro arguments are undefined" } */ + g(); +} diff --git a/gcc/testsuite/gcc.dg/cpp/c99-empty-macro-args.c b/gcc/testsuite/gcc.dg/cpp/c99-empty-macro-args.c new file mode 100644 index 00000000000..e1e0c61ec29 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/c99-empty-macro-args.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -pedantic" } */ + +#define f(a,b) f2(a,,b) +#define f2(a,b,c) a; b; c; +#define f3(a) a + +#define g() p() + +void p(void) {} + + +void foo(void) +{ + f(p(),p()); + f2(p(),,p()); + f3(); + g(); +} diff --git a/gcc/testsuite/gcc.dg/lower-subreg-1.c b/gcc/testsuite/gcc.dg/lower-subreg-1.c index 01851268c11..bb35d21bb50 100644 --- a/gcc/testsuite/gcc.dg/lower-subreg-1.c +++ b/gcc/testsuite/gcc.dg/lower-subreg-1.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { { ! mips64 } && { ! ia64-*-* } } } } */ +/* { dg-do compile { target { { { ! mips64 } && { ! ia64-*-* } } && { ! spu-*-* } } } } */ /* { dg-options "-O -fdump-rtl-subreg" } */ /* { dg-require-effective-target ilp32 } */ diff --git a/gcc/testsuite/gcc.dg/nrv3.c b/gcc/testsuite/gcc.dg/nrv3.c index 2b582c3ebe8..c28b8ec570d 100644 --- a/gcc/testsuite/gcc.dg/nrv3.c +++ b/gcc/testsuite/gcc.dg/nrv3.c @@ -3,7 +3,12 @@ /* { dg-do compile } */ /* { dg-options "-O -fdump-tree-optimized" } */ +#ifdef __SPU__ +/* SPU returns aggregates up to 1172 bytes in registers. */ +typedef struct { int x[300]; void *y; } S; +#else typedef struct { int x[20]; void *y; } S; +#endif typedef struct { int a; S b; } T; S nrv_candidate (void); void use_result (S, int); diff --git a/gcc/testsuite/gcc.dg/pr27095.c b/gcc/testsuite/gcc.dg/pr27095.c index 5ec39687a06..d274f4e8445 100644 --- a/gcc/testsuite/gcc.dg/pr27095.c +++ b/gcc/testsuite/gcc.dg/pr27095.c @@ -11,7 +11,7 @@ main (int argc, char **argv) memset (x, argc, strlen (x)); return 0; } -/* { dg-final { scan-assembler-not "(?n)strlen\(.*\n\)+.*strlen" { target { ! { powerpc*-*-darwin* hppa*-*-hpux* ia64-*-hpux* alpha*-*-* } } } } } */ +/* { dg-final { scan-assembler-not "(?n)strlen\(.*\n\)+.*strlen" { target { ! { powerpc*-*-darwin* hppa*-*-hpux* ia64-*-hpux* alpha*-*-* spu-*-* } } } } } */ /* hppa*-*-hpux* has an IMPORT statement for strlen (plus the branch). */ /* *-*-darwin* has something similar. */ /* { dg-final { scan-assembler-not "(?n)strlen\(.*\n\)+.*strlen\(.*\n\)+.*strlen" { target hppa*-*-hpux* } } } */ @@ -20,3 +20,5 @@ main (int argc, char **argv) /* { dg-final { scan-assembler-not "(?n)strlen\(.*\n\)+.*strlen\(.*\n\)+.*strlen\(.*\n\)+.*strlen" { target ia64-*-hpux* } } } */ /* alpha-*-* has a GOT load and the call. */ /* { dg-final { scan-assembler-not "(?n)jsr .*,strlen\(.*\n\)+.*jsr .*,strlen" { target alpha*-*-* } } } */ +/* spu-*-* has a branch hint and the call. */ +/* { dg-final { scan-assembler-not "(?n)brsl.*,strlen\(.*\n\)+.*brsl.*,strlen" { target spu-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/pr28243.c b/gcc/testsuite/gcc.dg/pr28243.c index c2797c0fb3f..12447a1c3d3 100644 --- a/gcc/testsuite/gcc.dg/pr28243.c +++ b/gcc/testsuite/gcc.dg/pr28243.c @@ -4,6 +4,7 @@ /* { dg-do compile } */ /* { dg-require-effective-target fpic } */ /* { dg-options "-O2 -ftracer -fPIC" } */ +/* { dg-skip-if "requires unsupported run-time relocation" { spu-*-* } { "*" } { "" } } */ struct displayfuncs { void (*init) (); diff --git a/gcc/testsuite/gcc.dg/pr35736.c b/gcc/testsuite/gcc.dg/pr35736.c new file mode 100644 index 00000000000..f411bb8a92f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr35736.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O -Wall" } */ + +void foo() +{ + while (1) + for (;;({ continue; })) + ; +} diff --git a/gcc/testsuite/gcc.dg/pr36227.c b/gcc/testsuite/gcc.dg/pr36227.c index d6657632b91..27fe0015505 100644 --- a/gcc/testsuite/gcc.dg/pr36227.c +++ b/gcc/testsuite/gcc.dg/pr36227.c @@ -1,12 +1,22 @@ /* { dg-do compile } */ /* { dg-options "-O2 -Wstrict-overflow=3" } */ +#if (__SIZEOF_LONG_LONG__ == __SIZEOF_POINTER__) +typedef unsigned long long ptrcast; +#elif (__SIZEOF_LONG__ == __SIZEOF_POINTER__) +typedef unsigned long ptrcast; +#elif (__SIZEOF_INT__ == __SIZEOF_POINTER__) +typedef unsigned int ptrcast; +#else +#error Add target support here +#endif volatile unsigned long * sat_add(volatile unsigned long *ptr, unsigned long i, volatile unsigned long *end) { - if ((unsigned long)ptr + i * sizeof(*ptr) > (unsigned long)ptr) /* { dg-bogus "pointer wraparound" } */ + if ((ptrcast)ptr + i * sizeof(*ptr) > (ptrcast)ptr) /* { dg-bogus "pointer wraparound" } */ return ptr + i; else return end; } + diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c index 24decb86fdf..a4b73e9cf5d 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c @@ -1,6 +1,6 @@ /* Test floating-point conversions. __float128 type. */ /* Origin: Joseph Myers <joseph@codesourcery.com> */ -/* { dg-do run { target { ia64-*-* || { { i?86-*-* x86_64-*-*} && lp64 } } } } */ +/* { dg-do run { target ia64-*-* i?86-*-* x86_64-*-* } } */ /* { dg-options "" } */ #include "fp-int-convert.h" diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c index e2b587c0cba..3e25f904dbe 100644 --- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c +++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c @@ -2,7 +2,6 @@ /* Origin: Joseph Myers <joseph@codesourcery.com> */ /* { dg-do run { target i?86-*-* x86_64-*-* ia64-*-* } } */ /* { dg-options "" } */ -/* { dg-options "-mmmx" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ #include "fp-int-convert.h" diff --git a/gcc/testsuite/gcc.dg/torture/ipa-pta-1.c b/gcc/testsuite/gcc.dg/torture/ipa-pta-1.c new file mode 100644 index 00000000000..c5adb259d26 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/ipa-pta-1.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-options "-fipa-pta -fdump-ipa-pta" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ + +struct X { char x; char y; }; + +void bar (char *p); + +void test1 (char a, char b, char c, char d, char e, char f, char g, char h) +{ + char *p = &a; + p++; + bar (p); +} + +void test2 (struct X a, char b, char c, char d, char e, char f, char g, char h) +{ + char *p = &a.x; + p++; + bar (p); +} + +void test3 (struct X a, char b, char c, char d, char e, char f, char g, char h) +{ + char *p = &a.y; + bar (p); +} + +void test4 (int a, char b, char c, char d, char e, char f, char g, char h) +{ + char *p = (char *)&a; + p++; + p++; + p++; + p++; + bar (p); +} + +/* { dg-final { scan-ipa-dump "bar.arg0 = { test4.arg0 test3.arg0 test2.arg0 test1.arg0 }" "pta" } } */ +/* { dg-final { cleanup-ipa-dump "pta" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr25947-1.c b/gcc/testsuite/gcc.dg/torture/pr25947-1.c index d52ef8c8e3f..8af6f8d4624 100644 --- a/gcc/testsuite/gcc.dg/torture/pr25947-1.c +++ b/gcc/testsuite/gcc.dg/torture/pr25947-1.c @@ -1,5 +1,6 @@ /* PR target/25947: define_split in cris.md caused unrecognized insn. */ /* { dg-options "-fpic" { target fpic } } */ +/* { dg-skip-if "requires unsupported run-time relocation" { spu-*-* } { "-O0" } { "" } } */ extern char *rl_line_buffer; extern int rl_point; diff --git a/gcc/testsuite/gcc.dg/torture/pr35842.c b/gcc/testsuite/gcc.dg/torture/pr35842.c index 05b26d84c11..05b26d84c11 100755..100644 --- a/gcc/testsuite/gcc.dg/torture/pr35842.c +++ b/gcc/testsuite/gcc.dg/torture/pr35842.c diff --git a/gcc/testsuite/gcc.dg/torture/pr36373-10.c b/gcc/testsuite/gcc.dg/torture/pr36373-10.c index b84e2544152..ed701772828 100644 --- a/gcc/testsuite/gcc.dg/torture/pr36373-10.c +++ b/gcc/testsuite/gcc.dg/torture/pr36373-10.c @@ -1,6 +1,14 @@ /* { dg-do run } */ +#if (__SIZEOF_LONG_LONG__ == __SIZEOF_POINTER__) +typedef unsigned long long uintptr_t; +#elif (__SIZEOF_LONG__ == __SIZEOF_POINTER__) typedef unsigned long uintptr_t; +#elif (__SIZEOF_INT__ == __SIZEOF_POINTER__) +typedef unsigned int uintptr_t; +#else +#error Add target support here +#endif void __attribute__((noinline)) foo(uintptr_t l) diff --git a/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c new file mode 100644 index 00000000000..2a8dc9e3037 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-options "-fdump-tree-alias" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ + +struct Foo { + int *p; +}; + +void __attribute__((noinline)) +foo (void *p) +{ + struct Foo *f = (struct Foo *)p - 1; + *f->p = 0; +} + +int bar (void) +{ + struct Foo f; + int i = 1; + f.p = &i; + foo (&f + 1); + return i; +} +extern void abort (void); +int main() +{ + if (bar () != 0) + abort (); + return 0; +} + +/* { dg-final { scan-tree-dump "ESCAPED = { ESCAPED NONLOCAL f .* i }" "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/pta-ptrarith-2.c b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-2.c new file mode 100644 index 00000000000..fb5b2e15ede --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pta-ptrarith-2.c @@ -0,0 +1,36 @@ +/* { dg-do run } */ +/* { dg-options "-fdump-tree-alias" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ + +struct Foo { + int **p; + int **q; +}; + +int __attribute__((noinline)) +bar (void) +{ + struct Foo f; + int j, i = 1; + char *p; + int *x = &i; + int *y = &j; + f.p = &y; + f.q = &x; + p = (char *)&f; + for (j = 0; j < sizeof (int *); ++j) + p++; + return ***(int ***)p; +} +extern void abort (void); +int main() +{ + if (bar () != 1) + abort (); + return 0; +} + +/* In theory = { i } is the correct solution. But it's not easy to scan + for that reliably, so just use what we create now. */ +/* { dg-final { scan-tree-dump "= { i j }" "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c index 28cdfd23181..d7aea1b8430 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c @@ -33,5 +33,5 @@ void test55 (int x, int y) that the && should be emitted (based on BRANCH_COST). Fix this by teaching dom to look through && and register all components as true. */ -/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail { ! "powerpc*-*-* cris-*-* crisv32-*-* mmix-*-* mips*-*-*" } } } } */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail { ! "powerpc*-*-* cris-*-* crisv32-*-* mmix-*-* mips*-*-* m68k*-*-*" } } } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c new file mode 100644 index 00000000000..c2b512a12e9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 --param max-fields-for-field-sensitive=2 -fdump-tree-alias" } */ + +struct Foo { + int *p, *q; +}; + +int foo (int ***x) __attribute__((pure)); + +int bar (int b) +{ + int i; + struct Foo f; + int *p, **q; + p = &i; + f.p = &i; + f.q = f.p; + if (b) + q = &f.p; + else + q = &f.q; + return foo (&q); +} + +/* { dg-final { scan-tree-dump "CALLUSED = { f.* i q }" "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-3.c index 3b7a547a6e7..85e444886d0 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-3.c @@ -5,7 +5,7 @@ When the condition is true, we distribute "(int) (a + b)" as "(int) a + (int) b", otherwise we keep the original. */ -/* { dg-do compile { target { ! mips64 } } } */ +/* { dg-do compile { target { { ! mips64 } && { ! spu-*-* } } } } */ /* { dg-options "-O -fwrapv -fdump-tree-fre-details" } */ /* From PR14844. */ diff --git a/gcc/testsuite/gcc.target/arm/neon/polytypes.c b/gcc/testsuite/gcc.target/arm/neon/polytypes.c index 9aca6671ae0..12e9b0a7f6a 100644 --- a/gcc/testsuite/gcc.target/arm/neon/polytypes.c +++ b/gcc/testsuite/gcc.target/arm/neon/polytypes.c @@ -28,7 +28,8 @@ void foo () poly8x16_t v128_8; poly16x8_t v128_16; - s64_8 (v64_8); /* { dg-error "use -flax-vector-conversions.*incompatible type for argument 1 of 's64_8'" } */ + s64_8 (v64_8); /* { dg-message "use -flax-vector-conversions" } */ + /* { dg-error "incompatible type for argument 1 of 's64_8'" "" { target *-*-* } 31 } */ u64_8 (v64_8); /* { dg-error "incompatible type for argument 1 of 'u64_8'" } */ p64_8 (v64_8); diff --git a/gcc/testsuite/gcc.target/i386/float128-1.c b/gcc/testsuite/gcc.target/i386/float128-1.c new file mode 100644 index 00000000000..9c6d22745f0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/float128-1.c @@ -0,0 +1,24 @@ +/* { dg-do run { target *-*-linux* } } */ +/* { dg-options "-O2 -msse2" } */ + +#include "sse2-check.h" + +extern void abort (void); + +typedef _Complex float __attribute__((mode(TC))) _Complex128; + +_Complex128 __attribute__ ((noinline)) +foo (_Complex128 x, _Complex128 y) +{ + return x * y; +} + +static void +sse2_test (void) +{ + _Complex128 a = 1.3q + 3.4qi, b = 5.6q + 7.8qi, c; + + c = foo (a, b); + if (__real__(c) == 0.0q || __imag__ (c) == 0.0q) + abort (); +} diff --git a/gcc/testsuite/gcc.target/i386/float128-2.c b/gcc/testsuite/gcc.target/i386/float128-2.c new file mode 100644 index 00000000000..94408d2ef35 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/float128-2.c @@ -0,0 +1,17 @@ +/* PR target/36710 */ + +/* { dg-do run { target *-*-linux* *-*-darwin* } } */ +/* { dg-options "-Os -msse2" } */ + +#include "sse2-check.h" + +extern void abort (void); + +static void +sse2_test (void) +{ + static volatile __float128 a = 123.0q; + + if ((int) a != 123) + abort (); +} diff --git a/gcc/testsuite/gcc.target/i386/pr32191.c b/gcc/testsuite/gcc.target/i386/pr32191.c index 0da5d5c5aae..f5238b01dee 100644 --- a/gcc/testsuite/gcc.target/i386/pr32191.c +++ b/gcc/testsuite/gcc.target/i386/pr32191.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-require-effective-target lp64 } */ /* { dg-options "-std=c99" } */ typedef _Complex float __attribute__((mode(TC))) _Complex128; diff --git a/gcc/testsuite/gcc.target/i386/pr32268.c b/gcc/testsuite/gcc.target/i386/pr32268.c index 472259c1eba..a5d673ad94f 100644 --- a/gcc/testsuite/gcc.target/i386/pr32268.c +++ b/gcc/testsuite/gcc.target/i386/pr32268.c @@ -1,5 +1,4 @@ /* { dg-do run { target *-*-linux* } } */ -/* { dg-require-effective-target lp64 } */ /* { dg-options "-O2" } */ extern void abort(void); diff --git a/gcc/testsuite/gcc.target/m68k/interrupt-2.c b/gcc/testsuite/gcc.target/m68k/interrupt-2.c new file mode 100644 index 00000000000..7d4cb68c121 --- /dev/null +++ b/gcc/testsuite/gcc.target/m68k/interrupt-2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +int x; +volatile unsigned int y; + +#define REPEAT10(X, Y) \ + X(Y##0); X(Y##1); X(Y##2); X(Y##3); X(Y##4); \ + X(Y##5); X(Y##6); X(Y##7); X(Y##8); X(Y##9) + +#define REPEAT30(X) REPEAT10 (X, 0); REPEAT10 (X, 1); REPEAT10 (X, 2) +#define IN(X) unsigned int x##X = y +#define OUT(X) y = x##X + +void __attribute__ ((interrupt_handler)) f1 (void) +{ + x = y + 11; +} + +void __attribute__ ((interrupt_handler)) f2 (void) +{ + REPEAT30 (IN); + REPEAT30 (OUT); +} diff --git a/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-1.c b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-1.c index 4c642258f7b..c12d08e0521 100644 --- a/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-1.c +++ b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-1.c @@ -1,15 +1,15 @@ /* { dg-do preprocess } */ /* { dg-mips-options "-mips2" } */ -#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) == defined (__mips16) +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 #error nonono #endif -#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) == defined (__mips16) +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 #error nonono #endif -#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) == defined (__mips16) +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 #error nonono #endif diff --git a/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-2.c b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-2.c index 4265e4167ba..eaae7801754 100644 --- a/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-2.c +++ b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-2.c @@ -1,19 +1,19 @@ /* { dg-do preprocess } */ /* { dg-mips-options "-mgp64" } */ -#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) == defined (__mips16) +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 #error nonono #endif -#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) == defined (__mips16) +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 #error nonono #endif -#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) == defined (__mips16) +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 #error nonono #endif -#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) == defined (__mips16) +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 #error nonono #endif diff --git a/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-3.c b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-3.c new file mode 100644 index 00000000000..faf50fc69ca --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-3.c @@ -0,0 +1,23 @@ +/* { dg-do preprocess { target mips16_attribute } } */ +/* { dg-mips-options "-mips2 -mips16" } */ +/* { dg-add-options mips16_attribute } */ + +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 +#error nonono +#endif + +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 +#error nonono +#endif + +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 +#error nonono +#endif + +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 +#error nonono +#endif + +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 +#error nonono +#endif diff --git a/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-4.c b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-4.c new file mode 100644 index 00000000000..b53f4b05b61 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/gcc-have-sync-compare-and-swap-4.c @@ -0,0 +1,23 @@ +/* { dg-do preprocess { target mips16_attribute } } */ +/* { dg-mips-options "-mgp64 -mips16" } */ +/* { dg-add-options mips16_attribute } */ + +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 +#error nonono +#endif + +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 +#error nonono +#endif + +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 +#error nonono +#endif + +#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 +#error nonono +#endif + +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 +#error nonono +#endif diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_tests_3.f90 b/gcc/testsuite/gfortran.dg/c_f_pointer_tests_3.f90 index 525af506428..3b28f52b4e7 100644 --- a/gcc/testsuite/gfortran.dg/c_f_pointer_tests_3.f90 +++ b/gcc/testsuite/gfortran.dg/c_f_pointer_tests_3.f90 @@ -14,11 +14,11 @@ program test type(c_funptr) :: cfunptr integer(4), pointer :: fptr integer(4), pointer :: fptr_array(:) -! procedure(integer(4)), pointer :: fprocptr ! TODO + procedure(integer(4)), pointer :: fprocptr call c_f_pointer(cptr, fptr) call c_f_pointer(cptr, fptr_array, [ 1 ]) -! call c_f_procpointer(cfunptr, fprocptr) ! TODO + call c_f_procpointer(cfunptr, fprocptr) end program test ! Make sure there is only a single function call: @@ -30,6 +30,6 @@ end program test ! { dg-final { scan-tree-dump-times " fptr = .integer.kind=4. .. cptr" 1 "original" } } ! ! Check c_f_procpointer -! TODO { scan-tree-dump-times " fprocptr = .integer.kind=4. .\\*<.*>. .void.. cfunptr;" 1 "original" } } TODO +! { dg-final { scan-tree-dump-times " fprocptr = .integer.kind=4. .\\*<.*>. .void.. cfunptr;" 1 "original" } } ! ! { dg-final { cleanup-tree-dump "original" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/pr36726.f90 b/gcc/testsuite/gfortran.dg/gomp/pr36726.f90 new file mode 100644 index 00000000000..99e170ad798 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/pr36726.f90 @@ -0,0 +1,20 @@ +! PR middle-end/36726 +! { dg-do compile } +! { dg-options "-fopenmp" } + +subroutine foo + integer, allocatable :: vs(:) + !$omp parallel private (vs) + allocate (vs(10)) + vs = 2 + deallocate (vs) + !$omp end parallel +end subroutine foo +subroutine bar + integer, allocatable :: vs(:) + !$omp parallel private (vs) + allocate (vs(10)) + vs = 2 + deallocate (vs) + !$omp end parallel +end subroutine bar diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_2.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_2.f90 new file mode 100644 index 00000000000..429b28c3016 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/matmul_bounds_2.f90 @@ -0,0 +1,16 @@ +! { dg-do run } +! { dg-options "-fbounds-check" } +! { dg-shouldfail "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic for dimension 2: is 2, should be 3" } +program main + real, dimension(3,2) :: a + real, dimension(2,3) :: b + real, dimension(:,:), allocatable :: ret + allocate (ret(2,2)) + a = 1.0 + b = 2.3 + ret = matmul(b,a) ! This is OK + deallocate(ret) + allocate(ret(3,2)) + ret = matmul(a,b) ! This should throw an error. +end program main +! { dg-output "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic for dimension 2: is 2, should be 3" } diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_3.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_3.f90 new file mode 100644 index 00000000000..c5830ded729 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/matmul_bounds_3.f90 @@ -0,0 +1,16 @@ +! { dg-do run } +! { dg-options "-fbounds-check" } +! { dg-shouldfail "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic for dimension 1: is 2, should be 3" } +program main + real, dimension(3,2) :: a + real, dimension(2,3) :: b + real, dimension(:,:), allocatable :: ret + allocate (ret(3,3)) + a = 1.0 + b = 2.3 + ret = matmul(a,b) ! This is OK + deallocate(ret) + allocate(ret(2,3)) + ret = matmul(a,b) ! This should throw an error. +end program main +! { dg-output "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic for dimension 1: is 2, should be 3" } diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_4.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_4.f90 new file mode 100644 index 00000000000..a61bacc1d2b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/matmul_bounds_4.f90 @@ -0,0 +1,16 @@ +! { dg-do run } +! { dg-options "-fbounds-check" } +! { dg-shouldfail "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic: is 3, should be 2" } +program main + real, dimension(3) :: a + real, dimension(3,2) :: b + real, dimension(:), allocatable :: ret + allocate (ret(2)) + a = 1.0 + b = 2.3 + ret = matmul(a,b) ! This is OK + deallocate(ret) + allocate(ret(3)) + ret = matmul(a,b) ! This should throw an error. +end program main +! { dg-output "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic: is 3, should be 2" } diff --git a/gcc/testsuite/gfortran.dg/matmul_bounds_5.f90 b/gcc/testsuite/gfortran.dg/matmul_bounds_5.f90 new file mode 100644 index 00000000000..4b20098f50f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/matmul_bounds_5.f90 @@ -0,0 +1,16 @@ +! { dg-do run } +! { dg-options "-fbounds-check" } +! { dg-shouldfail "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic: is 3, should be 2" } +program main + real, dimension(2,3) :: a + real, dimension(3) :: b + real, dimension(:), allocatable :: ret + allocate (ret(2)) + a = 1.0 + b = 2.3 + ret = matmul(a,b) ! This is OK + deallocate(ret) + allocate(ret(3)) + ret = matmul(a,b) ! This should throw an error. +end program main +! { dg-output "Fortran runtime error: Incorrect extent in return array in MATMUL intrinsic: is 3, should be 2" } diff --git a/gcc/testsuite/gfortran.dg/proc_decl_1.f90 b/gcc/testsuite/gfortran.dg/proc_decl_1.f90 index c01f7c6101e..3e7a3d18fb7 100644 --- a/gcc/testsuite/gfortran.dg/proc_decl_1.f90 +++ b/gcc/testsuite/gfortran.dg/proc_decl_1.f90 @@ -40,8 +40,6 @@ program prog procedure(dcos) :: my1 procedure(amax0) :: my2 ! { dg-error "not allowed in PROCEDURE statement" } - procedure(),pointer:: ptr ! { dg-error "not yet implemented" } - type t procedure(),pointer:: p ! { dg-error "not yet implemented" } end type diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_1.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_1.f90 new file mode 100644 index 00000000000..fe8e201000e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_1.f90 @@ -0,0 +1,73 @@ +! { dg-do run } +! +! basic tests of PROCEDURE POINTERS +! +! Contributed by Janus Weil <janus@gcc.gnu.org> + +module m +contains + subroutine proc1(arg) + character (5) :: arg + arg = "proc1" + end subroutine + integer function proc2(arg) + integer, intent(in) :: arg + proc2 = arg**2 + end function + complex function proc3(re, im) + real, intent(in) :: re, im + proc3 = complex (re, im) + end function +end module + +subroutine foo1 +end subroutine + +real function foo2() + foo2=6.3 +end function + +program procPtrTest + use m, only: proc1, proc2, proc3 + character (5) :: str + PROCEDURE(proc1), POINTER :: ptr1 + PROCEDURE(proc2), POINTER :: ptr2 + PROCEDURE(proc3), POINTER :: ptr3 => NULL() + PROCEDURE(REAL), SAVE, POINTER :: ptr4 + PROCEDURE(), POINTER :: ptr5,ptr6 + + EXTERNAL :: foo1,foo2 + real :: foo2 + + if(ASSOCIATED(ptr3)) call abort() + + NULLIFY(ptr1) + if (ASSOCIATED(ptr1)) call abort() + ptr1 => proc1 + if (.not. ASSOCIATED(ptr1)) call abort() + call ptr1 (str) + if (str .ne. "proc1") call abort () + + ptr2 => NULL() + if (ASSOCIATED(ptr2)) call abort() + ptr2 => proc2 + if (.not. ASSOCIATED(ptr2,proc2)) call abort() + if (10*ptr2 (10) .ne. 1000) call abort () + + ptr3 => NULL (ptr3) + if (ASSOCIATED(ptr3)) call abort() + ptr3 => proc3 + if (ptr3 (1.0, 2.0) .ne. (1.0, 2.0)) call abort () + + ptr4 => cos + if (ptr4(0.0)/=1.0) call abort() + + ptr5 => foo1 + call ptr5() + + ptr6 => foo2 + if (ptr6()/=6.3) call abort() + +end program + +! { dg-final { cleanup-modules "m" } } diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_2.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_2.f90 new file mode 100644 index 00000000000..d19b81d6e47 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_2.f90 @@ -0,0 +1,14 @@ +! { dg-do compile } +! +! checking invalid code for PROCEDURE POINTERS +! +! Contributed by Janus Weil <janus@gcc.gnu.org> + +PROCEDURE(REAL), POINTER :: ptr +PROCEDURE(REAL), SAVE :: noptr ! { dg-error "attribute conflicts with" } + +ptr => cos(4.0) ! { dg-error "Invalid character" } + +ALLOCATE(ptr) ! { dg-error "must be ALLOCATABLE" } + +end diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_3.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_3.f90 new file mode 100644 index 00000000000..34d4f1625fb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_3.f90 @@ -0,0 +1,45 @@ +! { dg-do run } +! +! PROCEDURE POINTERS without the PROCEDURE statement +! +! Contributed by Janus Weil <janus@gcc.gnu.org> + +real function e1(x) + real :: x + print *,'e1!',x + e1 = x * 3.0 +end function + +subroutine e2(a,b) + real, intent(inout) :: a + real, intent(in) :: b + print *,'e2!',a,b + a = a + b +end subroutine + +program proc_ptr_3 + +real, external, pointer :: fp + +pointer :: sp +interface + subroutine sp(a,b) + real, intent(inout) :: a + real, intent(in) :: b + end subroutine sp +end interface + +external :: e1,e2 +real :: c = 1.2 + +fp => e1 + +if (abs(fp(2.5)-7.5)>0.01) call abort() + +sp => e2 + +call sp(c,3.4) + +if (abs(c-4.6)>0.01) call abort() + +end diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_4.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_4.f90 new file mode 100644 index 00000000000..60b9e73af82 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_4.f90 @@ -0,0 +1,57 @@ +! { dg-do compile } +! +! PROCEDURE POINTERS & pointer-valued functions +! +! Contributed by Janus Weil <janus@gcc.gnu.org> + +interface + integer function f1() + end function +end interface + +interface + function f2() + integer, pointer :: f2 + end function +end interface + +interface + function pp1() + integer :: pp1 + end function +end interface +pointer :: pp1 + +pointer :: pp2 +interface + function pp2() + integer :: pp2 + end function +end interface + +pointer :: pp3 +interface + function pp3() + integer, pointer :: pp3 + end function +end interface + +interface + function pp4() + integer, pointer :: pp4 + end function +end interface +pointer :: pp4 + + +pp1 => f1 + +pp2 => pp1 + +f2 => f1 ! { dg-error "is not a variable" } + +pp3 => f2 + +pp4 => pp3 + +end
\ No newline at end of file diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_5.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_5.f90 new file mode 100644 index 00000000000..61cf8a35d10 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_5.f90 @@ -0,0 +1,33 @@ +! { dg-do run } +! +! NULL() initialization for PROCEDURE POINTERS +! +! Contributed by Tobias Burnus <burnus@gcc.gnu.org> + +program main +implicit none +call test(.true.) +call test(.false.) + +contains + +integer function hello() + hello = 42 +end function hello + +subroutine test(first) + logical :: first + integer :: i + procedure(integer), pointer :: x => null() + + if(first) then + if(associated(x)) call abort() + x => hello + else + if(.not. associated(x)) call abort() + i = x() + if(i /= 42) call abort() + end if + end subroutine test + +end program main diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_6.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_6.f90 new file mode 100644 index 00000000000..6a5c7e5f462 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_6.f90 @@ -0,0 +1,39 @@ +! { dg-do run } +! +! PROCEDURE POINTERS as actual/formal arguments +! +! Contributed by Janus Weil <janus@gcc.gnu.org> + +subroutine foo(j) + INTEGER, INTENT(OUT) :: j + j = 6 +end subroutine + +program proc_ptr_6 + +PROCEDURE(),POINTER :: ptr1 +PROCEDURE(REAL),POINTER :: ptr2 +EXTERNAL foo +INTEGER :: k = 0 + +ptr1 => foo +call s_in(ptr1,k) +if (k /= 6) call abort() + +call s_out(ptr2) +if (ptr2(-3.0) /= 3.0) call abort() + +contains + +subroutine s_in(p,i) + PROCEDURE(),POINTER,INTENT(IN) :: p + INTEGER, INTENT(OUT) :: i + call p(i) +end subroutine + +subroutine s_out(p) + PROCEDURE(REAL),POINTER,INTENT(OUT) :: p + p => abs +end subroutine + +end program diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_7.c b/gcc/testsuite/gfortran.dg/proc_ptr_7.c new file mode 100644 index 00000000000..7e9542fd86e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_7.c @@ -0,0 +1,10 @@ +/* Procedure pointer test. Used by proc_ptr_7.f90. + PR fortran/32580. */ + +int f(void) { + return 42; +} + +void assignf_(int(**ptr)(void)) { + *ptr = f; +} diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_7.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_7.f90 new file mode 100644 index 00000000000..8b1ea0a44b3 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_7.f90 @@ -0,0 +1,47 @@ +! { dg-do run } +! { dg-additional-sources proc_ptr_7.c } +! +! PR fortran/32580 +! Procedure pointer test +! +! Contributed by Tobias Burnus <burnus@gcc.gnu.org> + +program proc_pointer_test + use iso_c_binding, only: c_int + implicit none + + interface + subroutine assignF(f) + import c_int + procedure(Integer(c_int)), pointer :: f + end subroutine + end interface + + procedure(Integer(c_int)), pointer :: ptr + + call assignF(ptr) + if(ptr() /= 42) call abort() + + ptr => f55 + if(ptr() /= 55) call abort() + + call foo(ptr) + if(ptr() /= 65) call abort() + +contains + + subroutine foo(a) + procedure(integer(c_int)), pointer :: a + if(a() /= 55) call abort() + a => f65 + if(a() /= 65) call abort() + end subroutine foo + + integer(c_int) function f55() + f55 = 55 + end function f55 + + integer(c_int) function f65() + f65 = 65 + end function f65 +end program proc_pointer_test diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_8.c b/gcc/testsuite/gfortran.dg/proc_ptr_8.c new file mode 100644 index 00000000000..c732ff6667c --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_8.c @@ -0,0 +1,14 @@ +/* Used by proc_ptr_8.f90. + PR fortran/32580. */ + +int (*funpointer)(int); + +int f(int t) +{ + return t*3; +} + +void init() +{ + funpointer=f; +} diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_8.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_8.f90 new file mode 100644 index 00000000000..80d26619bc0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_8.f90 @@ -0,0 +1,34 @@ +! { dg-do run } +! { dg-additional-sources proc_ptr_8.c } +! +! PR fortran/32580 +! Original test case +! +! Contributed by Joost VandeVondele <jv244@cam.ac.uk> + +MODULE X + + USE ISO_C_BINDING + INTERFACE + INTEGER(KIND=C_INT) FUNCTION mytype( a ) BIND(C) + USE ISO_C_BINDING + INTEGER(KIND=C_INT), VALUE :: a + END FUNCTION + SUBROUTINE init() BIND(C,name="init") + END SUBROUTINE + END INTERFACE + + TYPE(C_FUNPTR), BIND(C,name="funpointer") :: funpointer + +END MODULE X + +USE X +PROCEDURE(mytype), POINTER :: ptype + +CALL init() +CALL C_F_PROCPOINTER(funpointer,ptype) +if (ptype(3) /= 9) call abort() + +END + +! { dg-final { cleanup-modules "X" } } diff --git a/gcc/testsuite/gfortran.dg/product_sum_bounds_1.f90 b/gcc/testsuite/gfortran.dg/product_sum_bounds_1.f90 new file mode 100644 index 00000000000..c6390896c17 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/product_sum_bounds_1.f90 @@ -0,0 +1,8 @@ +! { dg-do compile } +program main + real, dimension(4,3) :: a + real, dimension(2) :: b + a = 21. + b = product(a,dim=1) ! { dg-error "Different shape" } + b = sum(a,dim=2) ! { dg-error "Different shape" } +end program main diff --git a/gcc/testsuite/gnat.dg/loop_optimization3.adb b/gcc/testsuite/gnat.dg/loop_optimization3.adb new file mode 100644 index 00000000000..e69f535fb05 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization3.adb @@ -0,0 +1,15 @@ +-- { dg-do run } +-- { dg-options "-O" } + +with Loop_Optimization3_Pkg; use Loop_Optimization3_Pkg; + +procedure Loop_Optimization3 is + + type Arr is array (Integer range -3 .. 3) of Integer; + C : constant Arr := (1, others => F(2)); + +begin + if C /= (1, 2, 2, 2, 2, 2, 2) then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/loop_optimization3_pkg.adb b/gcc/testsuite/gnat.dg/loop_optimization3_pkg.adb new file mode 100644 index 00000000000..7a64815033d --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization3_pkg.adb @@ -0,0 +1,8 @@ +package body Loop_Optimization3_Pkg is + + function F (n : Integer) return Integer is + begin + return n; + end; + +end Loop_Optimization3_Pkg; diff --git a/gcc/testsuite/gnat.dg/loop_optimization3_pkg.ads b/gcc/testsuite/gnat.dg/loop_optimization3_pkg.ads new file mode 100644 index 00000000000..90f4fc32bad --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization3_pkg.ads @@ -0,0 +1,5 @@ +package Loop_Optimization3_Pkg is + + function F (n : Integer) return Integer; + +end Loop_Optimization3_Pkg; diff --git a/gcc/testsuite/lib/compat.exp b/gcc/testsuite/lib/compat.exp index 474af620d16..ee7cff56fbe 100644 --- a/gcc/testsuite/lib/compat.exp +++ b/gcc/testsuite/lib/compat.exp @@ -156,6 +156,8 @@ proc compat-run { testname objlist dest optall optfile optstr } { proc compat-get-options-main { src } { # dg-options sets a variable called dg-extra-tool-flags. set dg-extra-tool-flags "" + # dg-options sets a variable called tool_flags. + set tool_flags "" # dg-require-* sets dg-do-what. upvar dg-do-what dg-do-what @@ -164,6 +166,7 @@ proc compat-get-options-main { src } { foreach op $tmp { set cmd [lindex $op 0] if { ![string compare "dg-options" $cmd] \ + || [string match "dg-skip-if" $cmd] \ || [string match "dg-require-*" $cmd] } { set status [catch "$op" errmsg] if { $status != 0 } { @@ -275,6 +278,15 @@ proc compat-execute { src1 sid use_alt } { set extra_flags_3 [compat-get-options $src3] set compile_xfail_3 $compiler_conditional_xfail_data + # On the SPU, most of the compat test cases exceed local store size. + # Use automatic overlay support to make them fit. + if { [istarget spu-*-elf*] } { + set extra_flags_1 "$extra_flags_1 -Wl,--auto-overlay" + set extra_flags_1 "$extra_flags_1 -ffunction-sections" + set extra_flags_2 "$extra_flags_2 -ffunction-sections" + set extra_flags_3 "$extra_flags_3 -ffunction-sections" + } + # Define the names of the object files. regsub "sid" "sid_main_tst.o" $sid obj1 regsub "sid" "sid_x_tst.o" $sid obj2_tst diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index 9a3f12b5131..8d308d42461 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -354,6 +354,11 @@ proc remove-build-file { pat } { set file_list "[glob -nocomplain $pat]" verbose "remove-build-file `$file_list'" 2 foreach output_file $file_list { + if [is_remote host] { + # Ensure the host knows the file is gone by deleting there + # first. + remote_file host delete $output_file + } remote_file build delete $output_file } } diff --git a/gcc/testsuite/objc.dg/gnu-encoding/gnu-encoding.exp b/gcc/testsuite/objc.dg/gnu-encoding/gnu-encoding.exp index 7a0bdf3196c..dc4d9245a32 100644 --- a/gcc/testsuite/objc.dg/gnu-encoding/gnu-encoding.exp +++ b/gcc/testsuite/objc.dg/gnu-encoding/gnu-encoding.exp @@ -37,7 +37,7 @@ set generator_src "$srcdir/$subdir/struct-layout-encoding-1_generate.c" set generator_src "$generator_src $srcdir/$subdir/generate-random.c" set generator_src "$generator_src $srcdir/$subdir/generate-random_r.c" set generator_cmd "-o $generator $generator_src" -set status [remote_exec host "$HOSTCC $HOSTCFLAGS $generator_cmd"] +set status [remote_exec build "$HOSTCC $HOSTCFLAGS $generator_cmd"] set status [lindex $status 0] if { $status == 0 } then { file delete -force $tstobjdir diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c index b7363c377c0..7cc0285ff48 100644 --- a/gcc/tree-dump.c +++ b/gcc/tree-dump.c @@ -814,6 +814,7 @@ static const struct dump_option_value_info dump_options[] = {"address", TDF_ADDRESS}, {"slim", TDF_SLIM}, {"raw", TDF_RAW}, + {"graph", TDF_GRAPH}, {"details", TDF_DETAILS}, {"stats", TDF_STATS}, {"blocks", TDF_BLOCKS}, diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h index f700ab8347c..480ca41b417 100644 --- a/gcc/tree-flow-inline.h +++ b/gcc/tree-flow-inline.h @@ -881,7 +881,15 @@ factoring_name_p (const_tree name) return TREE_CODE (SSA_NAME_VAR (name)) == MEMORY_PARTITION_TAG; } -/* Return true if VAR is a clobbered by function calls. */ +/* Return true if VAR is used by function calls. */ +static inline bool +is_call_used (const_tree var) +{ + return (var_ann (var)->call_clobbered + || bitmap_bit_p (gimple_call_used_vars (cfun), DECL_UID (var))); +} + +/* Return true if VAR is clobbered by function calls. */ static inline bool is_call_clobbered (const_tree var) { diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 961054703db..5479c3342c7 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -1039,6 +1039,7 @@ void tree_ssa_iv_optimize (void); unsigned tree_predictive_commoning (void); bool parallelize_loops (void); +bool loop_only_exit_p (const struct loop *, const_edge); bool number_of_iterations_exit (struct loop *, edge, struct tree_niter_desc *niter, bool); tree find_loop_niter (struct loop *, edge *); diff --git a/gcc/tree-nrv.c b/gcc/tree-nrv.c index 13febcaf79b..cdf6c3fd9e6 100644 --- a/gcc/tree-nrv.c +++ b/gcc/tree-nrv.c @@ -265,7 +265,7 @@ dest_safe_for_nrv_p (tree dest) if (TREE_CODE (dest) == SSA_NAME) dest = SSA_NAME_VAR (dest); - if (is_call_clobbered (dest)) + if (is_call_used (dest)) return false; return true; diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c index 40c1d3f9c3b..21f362b9059 100644 --- a/gcc/tree-outof-ssa.c +++ b/gcc/tree-outof-ssa.c @@ -128,6 +128,8 @@ create_temp (tree t) set_symbol_mem_tag (tmp, symbol_mem_tag (t)); if (is_call_clobbered (t)) mark_call_clobbered (tmp, var_ann (t)->escape_mask); + if (bitmap_bit_p (gimple_call_used_vars (cfun), DECL_UID (t))) + bitmap_set_bit (gimple_call_used_vars (cfun), DECL_UID (tmp)); return tmp; } diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 391511f56a7..c50c6cd225b 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -308,6 +308,26 @@ sra_type_can_be_decomposed_p (tree type) return false; } +/* Returns true if the TYPE is one of the available va_list types. + Otherwise it returns false. + Note, that for multiple calling conventions there can be more + than just one va_list type present. */ + +static bool +is_va_list_type (tree type) +{ + tree h; + + if (type == NULL_TREE) + return false; + h = targetm.canonical_va_list_type (type); + if (h == NULL_TREE) + return false; + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (h)) + return true; + return false; +} + /* Return true if DECL can be decomposed into a set of independent (though not necessarily scalar) variables. */ @@ -360,9 +380,7 @@ decl_can_be_decomposed_p (tree var) tree-stdarg.c, as the decomposition is truly a win. This could also be fixed if the stdarg pass ran early, but this can't be done until we've aliasing information early too. See PR 30791. */ - if (early_sra - && TYPE_MAIN_VARIANT (TREE_TYPE (var)) - == TYPE_MAIN_VARIANT (va_list_type_node)) + if (early_sra && is_va_list_type (TREE_TYPE (var))) return false; return true; diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index ee0f4a7316a..d4a1e219a0c 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -2316,7 +2316,6 @@ compute_flow_sensitive_aliasing (struct alias_info *ai) tree ptr; timevar_push (TV_FLOW_SENSITIVE); - set_used_smts (); for (i = 0; VEC_iterate (tree, ai->processed_ptrs, i, ptr); i++) { diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index d4dfadbced0..da6b7855a81 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -2748,17 +2748,19 @@ optimize_stack_restore (basic_block bb, tree call, block_stmt_iterator i) static tree optimize_stdarg_builtin (tree call) { - tree callee, lhs, rhs; + tree callee, lhs, rhs, cfun_va_list; bool va_list_simple_ptr; if (TREE_CODE (call) != CALL_EXPR) return NULL_TREE; - va_list_simple_ptr = POINTER_TYPE_P (va_list_type_node) - && (TREE_TYPE (va_list_type_node) == void_type_node - || TREE_TYPE (va_list_type_node) == char_type_node); - callee = get_callee_fndecl (call); + + cfun_va_list = targetm.fn_abi_va_list (callee); + va_list_simple_ptr = POINTER_TYPE_P (cfun_va_list) + && (TREE_TYPE (cfun_va_list) == void_type_node + || TREE_TYPE (cfun_va_list) == char_type_node); + switch (DECL_FUNCTION_CODE (callee)) { case BUILT_IN_VA_START: @@ -2773,7 +2775,7 @@ optimize_stdarg_builtin (tree call) lhs = CALL_EXPR_ARG (call, 0); if (!POINTER_TYPE_P (TREE_TYPE (lhs)) || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (lhs))) - != TYPE_MAIN_VARIANT (va_list_type_node)) + != TYPE_MAIN_VARIANT (cfun_va_list)) return NULL_TREE; lhs = build_fold_indirect_ref (lhs); @@ -2792,13 +2794,13 @@ optimize_stdarg_builtin (tree call) lhs = CALL_EXPR_ARG (call, 0); if (!POINTER_TYPE_P (TREE_TYPE (lhs)) || TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (lhs))) - != TYPE_MAIN_VARIANT (va_list_type_node)) + != TYPE_MAIN_VARIANT (cfun_va_list)) return NULL_TREE; lhs = build_fold_indirect_ref (lhs); rhs = CALL_EXPR_ARG (call, 1); if (TYPE_MAIN_VARIANT (TREE_TYPE (rhs)) - != TYPE_MAIN_VARIANT (va_list_type_node)) + != TYPE_MAIN_VARIANT (cfun_va_list)) return NULL_TREE; rhs = fold_convert (TREE_TYPE (lhs), rhs); diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 41c37943656..ce5c05cd88f 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -3745,13 +3745,12 @@ may_eliminate_iv (struct ivopts_data *data, tree nit, period; struct loop *loop = data->current_loop; aff_tree bnd; - double_int period_value, max_niter; if (TREE_CODE (cand->iv->step) != INTEGER_CST) return false; - /* For now works only for exits that dominate the loop latch. TODO -- extend - for other conditions inside loop body. */ + /* For now works only for exits that dominate the loop latch. + TODO: extend to other conditions inside loop body. */ ex_bb = bb_for_stmt (use->stmt); if (use->stmt != last_stmt (ex_bb) || TREE_CODE (use->stmt) != COND_EXPR) @@ -3769,19 +3768,33 @@ may_eliminate_iv (struct ivopts_data *data, if (!nit) return false; - /* Determine whether we may use the variable to test whether niter iterations - elapsed. This is the case iff the period of the induction variable is - greater than the number of iterations. */ + /* Determine whether we can use the variable to test the exit condition. + This is the case iff the period of the induction variable is greater + than the number of iterations for which the exit condition is true. */ period = iv_period (cand->iv); - if (!period) - return false; - /* Compare the period with the estimate on the number of iterations of the - loop. */ - if (!estimated_loop_iterations (loop, true, &max_niter)) - return false; - period_value = tree_to_double_int (period); - if (double_int_ucmp (period_value, max_niter) <= 0) + /* If the number of iterations is constant, compare against it directly. */ + if (TREE_CODE (nit) == INTEGER_CST) + { + if (!tree_int_cst_lt (nit, period)) + return false; + } + + /* If not, and if this is the only possible exit of the loop, see whether + we can get a conservative estimate on the number of iterations of the + entire loop and compare against that instead. */ + else if (loop_only_exit_p (loop, exit)) + { + double_int period_value, max_niter; + if (!estimated_loop_iterations (loop, true, &max_niter)) + return false; + period_value = tree_to_double_int (period); + if (double_int_ucmp (max_niter, period_value) >= 0) + return false; + } + + /* Otherwise, punt. */ + else return false; cand_value_at (loop, cand, use->stmt, nit, &bnd); diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 74153fd294d..80b45c298b7 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -1672,7 +1672,7 @@ simplify_using_outer_evolutions (struct loop *loop, tree expr) /* Returns true if EXIT is the only possible exit from LOOP. */ -static bool +bool loop_only_exit_p (const struct loop *loop, const_edge exit) { basic_block *body; diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 553125641ce..6121437b245 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -220,8 +220,8 @@ struct variable_info /* True for variables whose size is not known or variable. */ unsigned int is_unknown_size_var:1; - /* True for variables that have unions somewhere in them. */ - unsigned int has_union:1; + /* True for (sub-)fields that represent a whole variable. */ + unsigned int is_full_var : 1; /* True if this is a heap variable. */ unsigned int is_heap_var:1; @@ -262,6 +262,7 @@ struct variable_info typedef struct variable_info *varinfo_t; static varinfo_t first_vi_for_offset (varinfo_t, unsigned HOST_WIDE_INT); +static varinfo_t lookup_vi_for_tree (tree); /* Pool of variable info structures. */ static alloc_pool variable_info_pool; @@ -375,7 +376,7 @@ new_var_info (tree t, unsigned int id, const char *name) ret->is_heap_var = false; ret->is_special_var = false; ret->is_unknown_size_var = false; - ret->has_union = false; + ret->is_full_var = false; var = t; if (TREE_CODE (var) == SSA_NAME) var = SSA_NAME_VAR (var); @@ -623,6 +624,96 @@ debug_constraints (void) dump_constraints (stderr); } +/* Print out to FILE the edge in the constraint graph that is created by + constraint c. The edge may have a label, depending on the type of + constraint that it represents. If complex1, e.g: a = *b, then the label + is "=*", if complex2, e.g: *a = b, then the label is "*=", if + complex with an offset, e.g: a = b + 8, then the label is "+". + Otherwise the edge has no label. */ + +void +dump_constraint_edge (FILE *file, constraint_t c) +{ + if (c->rhs.type != ADDRESSOF) + { + const char *src = get_varinfo_fc (c->rhs.var)->name; + const char *dst = get_varinfo_fc (c->lhs.var)->name; + fprintf (file, " \"%s\" -> \"%s\" ", src, dst); + /* Due to preprocessing of constraints, instructions like *a = *b are + illegal; thus, we do not have to handle such cases. */ + if (c->lhs.type == DEREF) + fprintf (file, " [ label=\"*=\" ] ;\n"); + else if (c->rhs.type == DEREF) + fprintf (file, " [ label=\"=*\" ] ;\n"); + else + { + /* We must check the case where the constraint is an offset. + In this case, it is treated as a complex constraint. */ + if (c->rhs.offset != c->lhs.offset) + fprintf (file, " [ label=\"+\" ] ;\n"); + else + fprintf (file, " ;\n"); + } + } +} + +/* Print the constraint graph in dot format. */ + +void +dump_constraint_graph (FILE *file) +{ + unsigned int i=0, size; + constraint_t c; + + /* Only print the graph if it has already been initialized: */ + if (!graph) + return; + + /* Print the constraints used to produce the constraint graph. The + constraints will be printed as comments in the dot file: */ + fprintf (file, "\n\n/* Constraints used in the constraint graph:\n"); + dump_constraints (file); + fprintf (file, "*/\n"); + + /* Prints the header of the dot file: */ + fprintf (file, "\n\n// The constraint graph in dot format:\n"); + fprintf (file, "strict digraph {\n"); + fprintf (file, " node [\n shape = box\n ]\n"); + fprintf (file, " edge [\n fontsize = \"12\"\n ]\n"); + fprintf (file, "\n // List of nodes in the constraint graph:\n"); + + /* The next lines print the nodes in the graph. In order to get the + number of nodes in the graph, we must choose the minimum between the + vector VEC (varinfo_t, varmap) and graph->size. If the graph has not + yet been initialized, then graph->size == 0, otherwise we must only + read nodes that have an entry in VEC (varinfo_t, varmap). */ + size = VEC_length (varinfo_t, varmap); + size = size < graph->size ? size : graph->size; + for (i = 0; i < size; i++) + { + const char *name = get_varinfo_fc (graph->rep[i])->name; + fprintf (file, " \"%s\" ;\n", name); + } + + /* Go over the list of constraints printing the edges in the constraint + graph. */ + fprintf (file, "\n // The constraint edges:\n"); + for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++) + if (c) + dump_constraint_edge (file, c); + + /* Prints the tail of the dot file. By now, only the closing bracket. */ + fprintf (file, "}\n\n\n"); +} + +/* Print out the constraint graph to stderr. */ + +void +debug_constraint_graph (void) +{ + dump_constraint_graph (stderr); +} + /* SOLVER FUNCTIONS The solver is a simple worklist solver, that works on the following @@ -755,23 +846,32 @@ solution_set_add (bitmap set, unsigned HOST_WIDE_INT offset) EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi) { - /* If this is a properly sized variable, only add offset if it's - less than end. Otherwise, it is globbed to a single - variable. */ + varinfo_t vi = get_varinfo (i); - if ((get_varinfo (i)->offset + offset) < get_varinfo (i)->fullsize) + /* If this is a variable with just one field just set its bit + in the result. */ + if (vi->is_artificial_var + || vi->is_unknown_size_var + || vi->is_full_var) + bitmap_set_bit (result, i); + else { - unsigned HOST_WIDE_INT fieldoffset = get_varinfo (i)->offset + offset; - varinfo_t v = first_vi_for_offset (get_varinfo (i), fieldoffset); + unsigned HOST_WIDE_INT fieldoffset = vi->offset + offset; + varinfo_t v = first_vi_for_offset (vi, fieldoffset); + /* If the result is outside of the variable use the last field. */ if (!v) - continue; + { + v = vi; + while (v->next != NULL) + v = v->next; + } bitmap_set_bit (result, v->id); - } - else if (get_varinfo (i)->is_artificial_var - || get_varinfo (i)->has_union - || get_varinfo (i)->is_unknown_size_var) - { - bitmap_set_bit (result, i); + /* If the result is not exactly at fieldoffset include the next + field as well. See get_constraint_for_ptr_offset for more + rationale. */ + if (v->offset != fieldoffset + && v->next != NULL) + bitmap_set_bit (result, v->next->id); } } @@ -1379,7 +1479,8 @@ type_safe (unsigned int n, unsigned HOST_WIDE_INT *offset) 0. */ if (ninfo->is_special_var || ninfo->is_artificial_var - || ninfo->is_unknown_size_var) + || ninfo->is_unknown_size_var + || ninfo->is_full_var) { *offset = 0; return true; @@ -1406,6 +1507,51 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c, goto done; } + /* For x = *ESCAPED and x = *CALLUSED we want to compute the + reachability set of the rhs var. As a pointer to a sub-field + of a variable can also reach all other fields of the variable + we simply have to expand the solution to contain all sub-fields + if one sub-field is contained. */ + if (c->rhs.var == escaped_id + || c->rhs.var == callused_id) + { + bitmap vars = NULL; + /* In a first pass record all variables we need to add all + sub-fields off. This avoids quadratic behavior. */ + EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi) + { + varinfo_t v = get_varinfo (j); + if (v->is_full_var) + continue; + + v = lookup_vi_for_tree (v->decl); + if (v->next != NULL) + { + if (vars == NULL) + vars = BITMAP_ALLOC (NULL); + bitmap_set_bit (vars, v->id); + } + } + /* In the second pass now do the addition to the solution and + to speed up solving add it to the delta as well. */ + if (vars != NULL) + { + EXECUTE_IF_SET_IN_BITMAP (vars, 0, j, bi) + { + varinfo_t v = get_varinfo (j); + for (; v != NULL; v = v->next) + { + if (bitmap_set_bit (sol, v->id)) + { + flag = true; + bitmap_set_bit (delta, v->id); + } + } + } + BITMAP_FREE (vars); + } + } + /* For each variable j in delta (Sol(y)), add an edge in the graph from j to x, and union Sol(j) into Sol(x). */ EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi) @@ -1418,6 +1564,7 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c, unsigned int t; v = first_vi_for_offset (get_varinfo (j), fieldoffset); + /* If the access is outside of the variable we can ignore it. */ if (!v) continue; t = find (v->id); @@ -1470,9 +1617,14 @@ do_ds_constraint (constraint_t c, bitmap delta) unsigned HOST_WIDE_INT fieldoffset = jvi->offset + loff; varinfo_t v; - v = first_vi_for_offset (get_varinfo (j), fieldoffset); - if (!v) - continue; + v = get_varinfo (j); + if (!v->is_full_var) + { + v = first_vi_for_offset (v, fieldoffset); + /* If the access is outside of the variable we can ignore it. */ + if (!v) + continue; + } t = find (v->id); if (bitmap_set_bit (get_varinfo (t)->solution, anything_id) @@ -1498,6 +1650,7 @@ do_ds_constraint (constraint_t c, bitmap delta) bitmap tmp; v = first_vi_for_offset (get_varinfo (j), fieldoffset); + /* If the access is outside of the variable we can ignore it. */ if (!v) continue; t = find (v->id); @@ -2560,12 +2713,6 @@ process_constraint (constraint_t t) gcc_assert (rhs.var < VEC_length (varinfo_t, varmap)); gcc_assert (lhs.var < VEC_length (varinfo_t, varmap)); - if (!use_field_sensitive) - { - t->rhs.offset = 0; - t->lhs.offset = 0; - } - /* ANYTHING == ANYTHING is pointless. */ if (lhs.var == anything_id && rhs.var == anything_id) return; @@ -2628,16 +2775,129 @@ could_have_pointers (tree t) /* Return the position, in bits, of FIELD_DECL from the beginning of its structure. */ -static unsigned HOST_WIDE_INT +static HOST_WIDE_INT bitpos_of_field (const tree fdecl) { - if (TREE_CODE (DECL_FIELD_OFFSET (fdecl)) != INTEGER_CST - || TREE_CODE (DECL_FIELD_BIT_OFFSET (fdecl)) != INTEGER_CST) + if (!host_integerp (DECL_FIELD_OFFSET (fdecl), 0) + || !host_integerp (DECL_FIELD_BIT_OFFSET (fdecl), 0)) return -1; - return (tree_low_cst (DECL_FIELD_OFFSET (fdecl), 1) * 8) - + tree_low_cst (DECL_FIELD_BIT_OFFSET (fdecl), 1); + return (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (fdecl)) * 8 + + TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (fdecl))); +} + + +/* Get constraint expressions for offsetting PTR by OFFSET. Stores the + resulting constraint expressions in *RESULTS. */ + +static void +get_constraint_for_ptr_offset (tree ptr, tree offset, + VEC (ce_s, heap) **results) +{ + struct constraint_expr *c; + unsigned int j, n; + unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset; + + /* If we do not do field-sensitive PTA adding offsets to pointers + does not change the points-to solution. */ + if (!use_field_sensitive) + { + get_constraint_for (ptr, results); + return; + } + + /* If the offset is not a non-negative integer constant that fits + in a HOST_WIDE_INT, we have to fall back to a conservative + solution which includes all sub-fields of all pointed-to + variables of ptr. + ??? As we do not have the ability to express this, fall back + to anything. */ + if (!host_integerp (offset, 1)) + { + struct constraint_expr temp; + temp.var = anything_id; + temp.type = SCALAR; + temp.offset = 0; + VEC_safe_push (ce_s, heap, *results, &temp); + return; + } + + /* Make sure the bit-offset also fits. */ + rhsunitoffset = TREE_INT_CST_LOW (offset); + rhsoffset = rhsunitoffset * BITS_PER_UNIT; + if (rhsunitoffset != rhsoffset / BITS_PER_UNIT) + { + struct constraint_expr temp; + temp.var = anything_id; + temp.type = SCALAR; + temp.offset = 0; + VEC_safe_push (ce_s, heap, *results, &temp); + return; + } + + get_constraint_for (ptr, results); + if (rhsoffset == 0) + return; + + /* As we are eventually appending to the solution do not use + VEC_iterate here. */ + n = VEC_length (ce_s, *results); + for (j = 0; j < n; j++) + { + varinfo_t curr; + c = VEC_index (ce_s, *results, j); + curr = get_varinfo (c->var); + + if (c->type == ADDRESSOF + && !curr->is_full_var) + { + varinfo_t temp, curr = get_varinfo (c->var); + + /* Search the sub-field which overlaps with the + pointed-to offset. As we deal with positive offsets + only, we can start the search from the current variable. */ + temp = first_vi_for_offset (curr, curr->offset + rhsoffset); + + /* If the result is outside of the variable we have to provide + a conservative result, as the variable is still reachable + from the resulting pointer (even though it technically + cannot point to anything). The last sub-field is such + a conservative result. + ??? If we always had a sub-field for &object + 1 then + we could represent this in a more precise way. */ + if (temp == NULL) + { + temp = curr; + while (temp->next != NULL) + temp = temp->next; + continue; + } + + /* If the found variable is not exactly at the pointed to + result, we have to include the next variable in the + solution as well. Otherwise two increments by offset / 2 + do not result in the same or a conservative superset + solution. */ + if (temp->offset != curr->offset + rhsoffset + && temp->next != NULL) + { + struct constraint_expr c2; + c2.var = temp->next->id; + c2.type = ADDRESSOF; + c2.offset = 0; + VEC_safe_push (ce_s, heap, *results, &c2); + } + c->var = temp->id; + c->offset = 0; + } + else if (c->type == ADDRESSOF + /* If this varinfo represents a full variable just use it. */ + && curr->is_full_var) + c->offset = 0; + else + c->offset = rhsoffset; + } } @@ -2677,15 +2937,18 @@ get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results, /* Pretend to take the address of the base, we'll take care of adding the required subset of sub-fields below. */ get_constraint_for_1 (t, results, true); - result = VEC_last (ce_s, *results); - gcc_assert (VEC_length (ce_s, *results) == 1); + result = VEC_last (ce_s, *results); /* This can also happen due to weird offsetof type macros. */ if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF) result->type = SCALAR; - if (result->type == SCALAR) + if (result->type == SCALAR + && get_varinfo (result->var)->is_full_var) + /* For single-field vars do not bother about the offset. */ + result->offset = 0; + else if (result->type == SCALAR) { /* In languages like C, you can access one past the end of an array. You aren't allowed to dereference it, so we can @@ -2714,12 +2977,25 @@ get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results, break; } } - /* assert that we found *some* field there. The user couldn't be - accessing *only* padding. */ - /* Still the user could access one past the end of an array - embedded in a struct resulting in accessing *only* padding. */ - gcc_assert (VEC_length (ce_s, *results) >= 1 - || ref_contains_array_ref (orig_t)); + /* If we are going to take the address of this field then + to be able to compute reachability correctly add at least + the last field of the variable. */ + if (address_p + && VEC_length (ce_s, *results) == 0) + { + curr = get_varinfo (cexpr.var); + while (curr->next != NULL) + curr = curr->next; + cexpr.var = curr->id; + VEC_safe_push (ce_s, heap, *results, &cexpr); + } + else + /* Assert that we found *some* field there. The user couldn't be + accessing *only* padding. */ + /* Still the user could access one past the end of an array + embedded in a struct resulting in accessing *only* padding. */ + gcc_assert (VEC_length (ce_s, *results) >= 1 + || ref_contains_array_ref (orig_t)); } else if (bitmaxsize == 0) { @@ -2863,24 +3139,10 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p) VEC_safe_push (ce_s, heap, *results, &temp); return; } - else - { - temp.var = anything_id; - temp.type = SCALAR; - temp.offset = 0; - VEC_safe_push (ce_s, heap, *results, &temp); - return; - } break; - default: - { - temp.type = ADDRESSOF; - temp.var = anything_id; - temp.offset = 0; - VEC_safe_push (ce_s, heap, *results, &temp); - return; - } + default:; } + break; } case tcc_reference: { @@ -2897,15 +3159,9 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p) case COMPONENT_REF: get_constraint_for_component_ref (t, results, address_p); return; - default: - { - temp.type = ADDRESSOF; - temp.var = anything_id; - temp.offset = 0; - VEC_safe_push (ce_s, heap, *results, &temp); - return; - } + default:; } + break; } case tcc_unary: { @@ -2926,15 +3182,19 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p) /* FALLTHRU */ } - default: - { - temp.type = ADDRESSOF; - temp.var = anything_id; - temp.offset = 0; - VEC_safe_push (ce_s, heap, *results, &temp); - return; - } + default:; } + break; + } + case tcc_binary: + { + if (TREE_CODE (t) == POINTER_PLUS_EXPR) + { + get_constraint_for_ptr_offset (TREE_OPERAND (t, 0), + TREE_OPERAND (t, 1), results); + return; + } + break; } case tcc_exceptional: { @@ -2945,37 +3205,28 @@ get_constraint_for_1 (tree t, VEC (ce_s, heap) **results, bool address_p) get_constraint_for_1 (PHI_RESULT (t), results, address_p); return; } - break; case SSA_NAME: { get_constraint_for_ssa_var (t, results, address_p); return; } - break; - default: - { - temp.type = ADDRESSOF; - temp.var = anything_id; - temp.offset = 0; - VEC_safe_push (ce_s, heap, *results, &temp); - return; - } + default:; } + break; } case tcc_declaration: { get_constraint_for_ssa_var (t, results, address_p); return; } - default: - { - temp.type = ADDRESSOF; - temp.var = anything_id; - temp.offset = 0; - VEC_safe_push (ce_s, heap, *results, &temp); - return; - } + default:; } + + /* The default fallback is a constraint from anything. */ + temp.type = ADDRESSOF; + temp.var = anything_id; + temp.offset = 0; + VEC_safe_push (ce_s, heap, *results, &temp); } /* Given a gimple tree T, return the constraint expression vector for it. */ @@ -3261,80 +3512,6 @@ do_structure_copy (tree lhsop, tree rhsop) } } - -/* Handle pointer arithmetic EXPR when creating aliasing constraints. - Expressions of the type PTR + CST can be handled in two ways: - - 1- If the constraint for PTR is ADDRESSOF for a non-structure - variable, then we can use it directly because adding or - subtracting a constant may not alter the original ADDRESSOF - constraint (i.e., pointer arithmetic may not legally go outside - an object's boundaries). - - 2- If the constraint for PTR is ADDRESSOF for a structure variable, - then if CST is a compile-time constant that can be used as an - offset, we can determine which sub-variable will be pointed-to - by the expression. - - Return true if the expression is handled. For any other kind of - expression, return false so that each operand can be added as a - separate constraint by the caller. */ - -static bool -handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr) -{ - tree op0, op1; - struct constraint_expr *c, *c2; - unsigned int i = 0; - unsigned int j = 0; - VEC (ce_s, heap) *temp = NULL; - unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset; - - if (TREE_CODE (expr) != POINTER_PLUS_EXPR) - return false; - - op0 = TREE_OPERAND (expr, 0); - op1 = TREE_OPERAND (expr, 1); - gcc_assert (POINTER_TYPE_P (TREE_TYPE (op0))); - - /* If the offset is not a non-negative integer constant that fits - in a HOST_WIDE_INT, we cannot handle it here. */ - if (!host_integerp (op1, 1)) - return false; - - /* Make sure the bit-offset also fits. */ - rhsunitoffset = TREE_INT_CST_LOW (op1); - rhsoffset = rhsunitoffset * BITS_PER_UNIT; - if (rhsunitoffset != rhsoffset / BITS_PER_UNIT) - return false; - - get_constraint_for (op0, &temp); - - for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++) - for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++) - { - if (c2->type == ADDRESSOF && rhsoffset != 0) - { - varinfo_t temp = get_varinfo (c2->var); - - /* An access one after the end of an array is valid, - so simply punt on accesses we cannot resolve. */ - temp = first_vi_for_offset (temp, rhsoffset); - if (temp == NULL) - continue; - c2->var = temp->id; - c2->offset = 0; - } - else - c2->offset = rhsoffset; - process_constraint (new_constraint (*c, *c2)); - } - - VEC_free (ce_s, heap, temp); - - return true; -} - /* Create a constraint ID = OP. */ static void @@ -3734,89 +3911,29 @@ find_func_aliases (tree origt) } } } - /* Otherwise, just a regular assignment statement. */ - else if (TREE_CODE (t) == GIMPLE_MODIFY_STMT) + /* Otherwise, just a regular assignment statement. Only care about + operations with pointer result, others are dealt with as escape + points if they have pointer operands. */ + else if (TREE_CODE (t) == GIMPLE_MODIFY_STMT + && could_have_pointers (GIMPLE_STMT_OPERAND (t, 0))) { tree lhsop = GIMPLE_STMT_OPERAND (t, 0); tree rhsop = GIMPLE_STMT_OPERAND (t, 1); - int i; - if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop)) - && AGGREGATE_TYPE_P (TREE_TYPE (rhsop))) - { - do_structure_copy (lhsop, rhsop); - } + if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop))) + do_structure_copy (lhsop, rhsop); else { - /* Only care about operations with pointers, structures - containing pointers, dereferences, and call expressions. */ - if (could_have_pointers (lhsop) - || TREE_CODE (rhsop) == CALL_EXPR) + unsigned int j; + get_constraint_for (lhsop, &lhsc); + get_constraint_for (rhsop, &rhsc); + for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++) { - get_constraint_for (lhsop, &lhsc); - switch (TREE_CODE_CLASS (TREE_CODE (rhsop))) - { - /* RHS that consist of unary operations, - exceptional types, or bare decls/constants, get - handled directly by get_constraint_for. */ - case tcc_reference: - case tcc_declaration: - case tcc_constant: - case tcc_exceptional: - case tcc_expression: - case tcc_vl_exp: - case tcc_unary: - { - unsigned int j; - - get_constraint_for (rhsop, &rhsc); - for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++) - { - struct constraint_expr *c2; - unsigned int k; - - for (k = 0; VEC_iterate (ce_s, rhsc, k, c2); k++) - process_constraint (new_constraint (*c, *c2)); - } - - } - break; + struct constraint_expr *c2; + unsigned int k; - case tcc_binary: - { - /* For pointer arithmetic of the form - PTR + CST, we can simply use PTR's - constraint because pointer arithmetic is - not allowed to go out of bounds. */ - if (handle_ptr_arith (lhsc, rhsop)) - break; - } - /* FALLTHRU */ - - /* Otherwise, walk each operand. Notice that we - can't use the operand interface because we need - to process expressions other than simple operands - (e.g. INDIRECT_REF, ADDR_EXPR, CALL_EXPR). */ - default: - for (i = 0; i < TREE_OPERAND_LENGTH (rhsop); i++) - { - tree op = TREE_OPERAND (rhsop, i); - unsigned int j; - - gcc_assert (VEC_length (ce_s, rhsc) == 0); - get_constraint_for (op, &rhsc); - for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++) - { - struct constraint_expr *c2; - while (VEC_length (ce_s, rhsc) > 0) - { - c2 = VEC_last (ce_s, rhsc); - process_constraint (new_constraint (*c, *c2)); - VEC_pop (ce_s, rhsc); - } - } - } - } + for (k = 0; VEC_iterate (ce_s, rhsc, k, c2); k++) + process_constraint (new_constraint (*c, *c2)); } } } @@ -3963,17 +4080,15 @@ insert_into_field_list_sorted (varinfo_t base, varinfo_t field) struct fieldoff { - /* Type of the field. */ - tree type; + /* Offset from the base of the base containing object to this field. */ + HOST_WIDE_INT offset; /* Size, in bits, of the field. */ - tree size; + unsigned HOST_WIDE_INT size; - /* Field. */ - tree decl; + unsigned has_unknown_size : 1; - /* Offset from the base of the base containing object to this field. */ - HOST_WIDE_INT offset; + unsigned may_have_pointers : 1; }; typedef struct fieldoff fieldoff_s; @@ -3994,10 +4109,10 @@ fieldoff_compare (const void *pa, const void *pb) else if (foa->offset > fob->offset) return 1; - foasize = TREE_INT_CST_LOW (foa->size); - fobsize = TREE_INT_CST_LOW (fob->size); + foasize = foa->size; + fobsize = fob->size; if (foasize < fobsize) - return - 1; + return -1; else if (foasize > fobsize) return 1; return 0; @@ -4041,14 +4156,11 @@ var_can_have_subvars (const_tree v) OFFSET is used to keep track of the offset in this entire structure, rather than just the immediately containing structure. - Returns the number of fields pushed. - - HAS_UNION is set to true if we find a union type as a field of - TYPE. */ + Returns the number of fields pushed. */ static int push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, - HOST_WIDE_INT offset, bool *has_union) + HOST_WIDE_INT offset) { tree field; int count = 0; @@ -4067,19 +4179,14 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, { bool push = false; int pushed = 0; + HOST_WIDE_INT foff = bitpos_of_field (field); - if (has_union - && (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE - || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)) - *has_union = true; - - if (!var_can_have_subvars (field)) + if (!var_can_have_subvars (field) + || TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE + || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) push = true; else if (!(pushed = push_fields_onto_fieldstack - (TREE_TYPE (field), - fieldstack, - offset + bitpos_of_field (field), - has_union)) + (TREE_TYPE (field), fieldstack, offset + foff)) && (DECL_SIZE (field) && !integer_zerop (DECL_SIZE (field)))) /* Empty structures may have actual size, like in C++. So @@ -4089,14 +4196,39 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, if (push) { - fieldoff_s *pair; - - pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL); - pair->type = TREE_TYPE (field); - pair->size = DECL_SIZE (field); - pair->decl = field; - pair->offset = offset + bitpos_of_field (field); - count++; + fieldoff_s *pair = NULL; + bool has_unknown_size = false; + + if (!VEC_empty (fieldoff_s, *fieldstack)) + pair = VEC_last (fieldoff_s, *fieldstack); + + if (!DECL_SIZE (field) + || !host_integerp (DECL_SIZE (field), 1)) + has_unknown_size = true; + + /* If adjacent fields do not contain pointers merge them. */ + if (pair + && !pair->may_have_pointers + && !could_have_pointers (field) + && !pair->has_unknown_size + && !has_unknown_size + && pair->offset + (HOST_WIDE_INT)pair->size == offset + foff) + { + pair = VEC_last (fieldoff_s, *fieldstack); + pair->size += TREE_INT_CST_LOW (DECL_SIZE (field)); + } + else + { + pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL); + pair->offset = offset + foff; + pair->has_unknown_size = has_unknown_size; + if (!has_unknown_size) + pair->size = TREE_INT_CST_LOW (DECL_SIZE (field)); + else + pair->size = -1; + pair->may_have_pointers = could_have_pointers (field); + count++; + } } else count += pushed; @@ -4162,7 +4294,6 @@ create_function_info_for (tree decl, const char *name) vi = new_var_info (decl, index, name); vi->decl = decl; vi->offset = 0; - vi->has_union = 0; vi->size = 1; vi->fullsize = count_num_arguments (decl, &is_varargs) + 1; insert_vi_for_tree (vi->decl, vi); @@ -4171,8 +4302,7 @@ create_function_info_for (tree decl, const char *name) stats.total_vars++; /* If it's varargs, we don't know how many arguments it has, so we - can't do much. - */ + can't do much. */ if (is_varargs) { vi->fullsize = ~0; @@ -4206,8 +4336,8 @@ create_function_info_for (tree decl, const char *name) VEC_safe_push (varinfo_t, heap, varmap, argvi); argvi->offset = i; argvi->size = 1; + argvi->is_full_var = true; argvi->fullsize = vi->fullsize; - argvi->has_union = false; insert_into_field_list_sorted (vi, argvi); stats.total_vars ++; if (arg) @@ -4243,7 +4373,7 @@ create_function_info_for (tree decl, const char *name) resultvi->offset = i; resultvi->size = 1; resultvi->fullsize = vi->fullsize; - resultvi->has_union = false; + resultvi->is_full_var = true; insert_into_field_list_sorted (vi, resultvi); stats.total_vars ++; if (DECL_RESULT (decl)) @@ -4283,25 +4413,14 @@ create_variable_info_for (tree decl, const char *name) varinfo_t vi; tree decltype = TREE_TYPE (decl); tree declsize = DECL_P (decl) ? DECL_SIZE (decl) : TYPE_SIZE (decltype); - bool notokay = false; - bool hasunion; bool is_global = DECL_P (decl) ? is_global_var (decl) : false; VEC (fieldoff_s,heap) *fieldstack = NULL; if (TREE_CODE (decl) == FUNCTION_DECL && in_ipa_mode) return create_function_info_for (decl, name); - hasunion = TREE_CODE (decltype) == UNION_TYPE - || TREE_CODE (decltype) == QUAL_UNION_TYPE; - if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion) - { - push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion); - if (hasunion) - { - VEC_free (fieldoff_s, heap, fieldstack); - notokay = true; - } - } + if (var_can_have_subvars (decl) && use_field_sensitive) + push_fields_onto_fieldstack (decltype, &fieldstack, 0); /* If the variable doesn't have subvars, we may end up needing to sort the field list and create fake variables for all the @@ -4309,11 +4428,8 @@ create_variable_info_for (tree decl, const char *name) vi = new_var_info (decl, index, name); vi->decl = decl; vi->offset = 0; - vi->has_union = hasunion; if (!declsize - || TREE_CODE (declsize) != INTEGER_CST - || TREE_CODE (decltype) == UNION_TYPE - || TREE_CODE (decltype) == QUAL_UNION_TYPE) + || !host_integerp (declsize, 1)) { vi->is_unknown_size_var = true; vi->fullsize = ~0; @@ -4333,7 +4449,6 @@ create_variable_info_for (tree decl, const char *name) stats.total_vars++; if (use_field_sensitive - && !notokay && !vi->is_unknown_size_var && var_can_have_subvars (decl) && VEC_length (fieldoff_s, fieldstack) > 1 @@ -4341,12 +4456,12 @@ create_variable_info_for (tree decl, const char *name) { unsigned int newindex = VEC_length (varinfo_t, varmap); fieldoff_s *fo = NULL; + bool notokay = false; unsigned int i; for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++) { - if (! fo->size - || TREE_CODE (fo->size) != INTEGER_CST + if (fo->has_unknown_size || fo->offset < 0) { notokay = true; @@ -4377,11 +4492,12 @@ create_variable_info_for (tree decl, const char *name) vi->is_unknown_size_var = 1; vi->fullsize = ~0; vi->size = ~0; + vi->is_full_var = true; VEC_free (fieldoff_s, heap, fieldstack); return index; } - vi->size = TREE_INT_CST_LOW (fo->size); + vi->size = fo->size; vi->offset = fo->offset; for (i = VEC_length (fieldoff_s, fieldstack) - 1; i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo); @@ -4394,28 +4510,27 @@ create_variable_info_for (tree decl, const char *name) newindex = VEC_length (varinfo_t, varmap); if (dump_file) { - if (fo->decl) - asprintf (&tempname, "%s.%s", - vi->name, alias_get_name (fo->decl)); - else - asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC, - vi->name, fo->offset); + asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC + "+" HOST_WIDE_INT_PRINT_DEC, + vi->name, fo->offset, fo->size); newname = ggc_strdup (tempname); free (tempname); } newvi = new_var_info (decl, newindex, newname); newvi->offset = fo->offset; - newvi->size = TREE_INT_CST_LOW (fo->size); + newvi->size = fo->size; newvi->fullsize = vi->fullsize; insert_into_field_list (vi, newvi); VEC_safe_push (varinfo_t, heap, varmap, newvi); if (is_global && (!flag_whole_program || !in_ipa_mode) - && (!fo->decl || could_have_pointers (fo->decl))) + && fo->may_have_pointers) make_constraint_from (newvi, escaped_id); stats.total_vars++; } } + else + vi->is_full_var = true; VEC_free (fieldoff_s, heap, fieldstack); @@ -4659,61 +4774,6 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed, static bool have_alias_info = false; -/* The list of SMT's that are in use by our pointer variables. This - is the set of SMT's for all pointers that can point to anything. */ -static bitmap used_smts; - -/* Due to the ordering of points-to set calculation and SMT - calculation being a bit co-dependent, we can't just calculate SMT - used info whenever we want, we have to calculate it around the time - that find_what_p_points_to is called. */ - -/* Mark which SMT's are in use by points-to anything variables. */ - -void -set_used_smts (void) -{ - int i; - varinfo_t vi; - used_smts = BITMAP_ALLOC (&pta_obstack); - - for (i = 0; VEC_iterate (varinfo_t, varmap, i, vi); i++) - { - tree var = vi->decl; - varinfo_t withsolution = get_varinfo (find (i)); - tree smt; - var_ann_t va; - struct ptr_info_def *pi = NULL; - - /* For parm decls, the pointer info may be under the default - def. */ - if (TREE_CODE (vi->decl) == PARM_DECL - && gimple_default_def (cfun, var)) - pi = SSA_NAME_PTR_INFO (gimple_default_def (cfun, var)); - else if (TREE_CODE (var) == SSA_NAME) - pi = SSA_NAME_PTR_INFO (var); - - /* Skip the special variables and those that can't be aliased. */ - if (vi->is_special_var - || !SSA_VAR_P (var) - || (pi && !pi->memory_tag_needed) - || (TREE_CODE (var) == VAR_DECL && !may_be_aliased (var)) - || !POINTER_TYPE_P (TREE_TYPE (var))) - continue; - - if (TREE_CODE (var) == SSA_NAME) - var = SSA_NAME_VAR (var); - - va = var_ann (var); - if (!va) - continue; - - smt = va->symbol_mem_tag; - if (smt && bitmap_bit_p (withsolution->solution, anything_id)) - bitmap_set_bit (used_smts, DECL_UID (smt)); - } -} - /* Given a pointer variable P, fill in its points-to set, or return false if we can't. Rather than return false for variables that point-to anything, we @@ -5167,6 +5227,8 @@ init_base_vars (void) static void init_alias_vars (void) { + use_field_sensitive = (MAX_FIELDS_FOR_FIELD_SENSITIVE > 1); + bitmap_obstack_initialize (&pta_obstack); bitmap_obstack_initialize (&oldpta_obstack); bitmap_obstack_initialize (&predbitmap_obstack); @@ -5425,6 +5487,10 @@ compute_points_to_sets (void) free_var_substitution_info (si); build_succ_graph (); + + if (dump_file && (dump_flags & TDF_GRAPH)) + dump_constraint_graph (dump_file); + move_complex_constraints (graph); if (dump_file) diff --git a/gcc/tree-ssa-structalias.h b/gcc/tree-ssa-structalias.h index 7d468b42f91..0d0d6bdf073 100644 --- a/gcc/tree-ssa-structalias.h +++ b/gcc/tree-ssa-structalias.h @@ -32,13 +32,15 @@ void update_mem_sym_stats_from_stmt (tree, tree, long, long); extern void compute_points_to_sets (void); extern void delete_points_to_sets (void); extern void dump_constraint (FILE *, constraint_t); +extern void dump_constraint_edge (FILE *, constraint_t); extern void dump_constraints (FILE *); +extern void dump_constraint_graph (FILE *); extern void debug_constraint (constraint_t); extern void debug_constraints (void); +extern void debug_constraint_graph (void); extern void dump_solution_for_var (FILE *, unsigned int); extern void debug_solution_for_var (unsigned int); extern void dump_sa_points_to_info (FILE *); extern void debug_sa_points_to_info (void); -extern void set_used_smts (void); #endif /* TREE_SSA_STRUCTALIAS_H */ diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c index 728c37d4d6d..f9228872dc2 100644 --- a/gcc/tree-stdarg.c +++ b/gcc/tree-stdarg.c @@ -605,6 +605,7 @@ execute_optimize_stdarg (void) bool va_list_simple_ptr; struct stdarg_info si; const char *funcname = NULL; + tree cfun_va_list; cfun->va_list_gpr_size = 0; cfun->va_list_fpr_size = 0; @@ -615,10 +616,11 @@ execute_optimize_stdarg (void) if (dump_file) funcname = lang_hooks.decl_printable_name (current_function_decl, 2); - va_list_simple_ptr = POINTER_TYPE_P (va_list_type_node) - && (TREE_TYPE (va_list_type_node) == void_type_node - || TREE_TYPE (va_list_type_node) == char_type_node); - gcc_assert (is_gimple_reg_type (va_list_type_node) == va_list_simple_ptr); + cfun_va_list = targetm.fn_abi_va_list (cfun->decl); + va_list_simple_ptr = POINTER_TYPE_P (cfun_va_list) + && (TREE_TYPE (cfun_va_list) == void_type_node + || TREE_TYPE (cfun_va_list) == char_type_node); + gcc_assert (is_gimple_reg_type (cfun_va_list) == va_list_simple_ptr); FOR_EACH_BB (bb) { @@ -671,7 +673,7 @@ execute_optimize_stdarg (void) ap = TREE_OPERAND (ap, 0); } if (TYPE_MAIN_VARIANT (TREE_TYPE (ap)) - != TYPE_MAIN_VARIANT (va_list_type_node) + != TYPE_MAIN_VARIANT (targetm.fn_abi_va_list (cfun->decl)) || TREE_CODE (ap) != VAR_DECL) { va_list_escapes = true; diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index 68d6b50d1bd..0ce5fc91ead 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -482,7 +482,7 @@ build_one_array (tree swtch, int num, tree arr_index_type, tree phi, tree tidx) fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE, NULL_TREE); - load = build2 (GIMPLE_MODIFY_STMT, void_type_node, name, fetch); + load = build_gimple_modify_stmt (name, fetch); SSA_NAME_DEF_STMT (name) = load; bsi = bsi_for_stmt (swtch); @@ -507,13 +507,17 @@ build_arrays (tree swtch) tree phi = phi_nodes (info.final_bb); int i; + bsi = bsi_for_stmt (swtch); + arr_index_type = build_index_type (info.range_size); tidx = make_rename_temp (arr_index_type, "csti"); - sub = build2 (MINUS_EXPR, TREE_TYPE (info.index_expr), info.index_expr, - fold_convert (TREE_TYPE (info.index_expr), info.range_min)); - sub = build2 (GIMPLE_MODIFY_STMT, void_type_node, tidx, sub); + sub = fold_build2 (MINUS_EXPR, TREE_TYPE (info.index_expr), info.index_expr, + fold_convert (TREE_TYPE (info.index_expr), + info.range_min)); + sub = force_gimple_operand_bsi (&bsi, fold_convert (arr_index_type, sub), + false, NULL, true, BSI_SAME_STMT); + sub = build_gimple_modify_stmt (tidx, sub); - bsi = bsi_for_stmt (swtch); bsi_insert_before (&bsi, sub, BSI_SAME_STMT); mark_symbols_for_renaming (sub); info.arr_ref_first = sub; @@ -539,8 +543,7 @@ gen_def_assigns (block_stmt_iterator *bsi) NULL_TREE); info.target_outbound_names[i] = name; - assign = build2 (GIMPLE_MODIFY_STMT, void_type_node, name, - info.default_values[i]); + assign = build_gimple_modify_stmt (name, info.default_values[i]); SSA_NAME_DEF_STMT (name) = assign; bsi_insert_before (bsi, assign, BSI_SAME_STMT); find_new_referenced_vars (&assign); @@ -639,15 +642,17 @@ gen_inbound_check (tree swtch) bsi = bsi_for_stmt (info.arr_ref_first); tmp_u = make_rename_temp (utype, "csui"); - cast = build1 (NOP_EXPR, utype, info.index_expr); - cast_assign = build2 (GIMPLE_MODIFY_STMT, void_type_node, tmp_u, cast); + cast = fold_convert (utype, info.index_expr); + cast_assign = build_gimple_modify_stmt (tmp_u, cast); find_new_referenced_vars (&cast_assign); bsi_insert_before (&bsi, cast_assign, BSI_SAME_STMT); mark_symbols_for_renaming (cast_assign); ulb = fold_convert (utype, info.range_min); - minus = build2 (MINUS_EXPR, utype, tmp_u, ulb); - minus_assign = build2 (GIMPLE_MODIFY_STMT, void_type_node, tmp_u, minus); + minus = fold_build2 (MINUS_EXPR, utype, tmp_u, ulb); + minus = force_gimple_operand_bsi (&bsi, minus, false, NULL, true, + BSI_SAME_STMT); + minus_assign = build_gimple_modify_stmt (tmp_u, minus); find_new_referenced_vars (&minus_assign); bsi_insert_before (&bsi, minus_assign, BSI_SAME_STMT); mark_symbols_for_renaming (minus_assign); diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c index 09a2eafe119..92127b4b7af 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -138,14 +138,14 @@ suitable_for_tail_opt_p (void) if (cfun->stdarg) return false; - /* No local variable nor structure field should be call-clobbered. We + /* No local variable nor structure field should be call-used. We ignore any kind of memory tag, as these are not real variables. */ FOR_EACH_REFERENCED_VAR (var, rvi) { if (!is_global_var (var) && !MTAG_P (var) - && (gimple_aliases_computed_p (cfun) ? is_call_clobbered (var) + && (gimple_aliases_computed_p (cfun)? is_call_used (var) : TREE_ADDRESSABLE (var))) return false; } diff --git a/gcc/tree.c b/gcc/tree.c index d9e4e7f18db..97b53bd951c 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -1827,6 +1827,24 @@ tree_cons_stat (tree purpose, tree value, tree chain MEM_STAT_DECL) return node; } +/* Return the elements of a CONSTRUCTOR as a TREE_LIST. */ + +tree +ctor_to_list (tree ctor) +{ + tree list = NULL_TREE; + tree *p = &list; + unsigned ix; + tree purpose, val; + + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), ix, purpose, val) + { + *p = build_tree_list (purpose, val); + p = &TREE_CHAIN (*p); + } + + return list; +} /* Return the size nominally occupied by an object of type TYPE when it resides in memory. The value is measured in units of bytes, @@ -7377,7 +7395,16 @@ build_common_tree_nodes_2 (int short_double) complex_long_double_type_node = build_complex_type (long_double_type_node); /* Make fixed-point nodes based on sat/non-sat and signed/unsigned. */ -#define MAKE_FIXED_TYPE_NODE(KIND,WIDTH,SIZE) \ +#define MAKE_FIXED_TYPE_NODE(KIND,SIZE) \ + sat_ ## KIND ## _type_node = \ + make_sat_signed_ ## KIND ## _type (SIZE); \ + sat_unsigned_ ## KIND ## _type_node = \ + make_sat_unsigned_ ## KIND ## _type (SIZE); \ + KIND ## _type_node = make_signed_ ## KIND ## _type (SIZE); \ + unsigned_ ## KIND ## _type_node = \ + make_unsigned_ ## KIND ## _type (SIZE); + +#define MAKE_FIXED_TYPE_NODE_WIDTH(KIND,WIDTH,SIZE) \ sat_ ## WIDTH ## KIND ## _type_node = \ make_sat_signed_ ## KIND ## _type (SIZE); \ sat_unsigned_ ## WIDTH ## KIND ## _type_node = \ @@ -7388,10 +7415,10 @@ build_common_tree_nodes_2 (int short_double) /* Make fixed-point type nodes based on four different widths. */ #define MAKE_FIXED_TYPE_NODE_FAMILY(N1,N2) \ - MAKE_FIXED_TYPE_NODE (N1, short_, SHORT_ ## N2 ## _TYPE_SIZE) \ - MAKE_FIXED_TYPE_NODE (N1, , N2 ## _TYPE_SIZE) \ - MAKE_FIXED_TYPE_NODE (N1, long_, LONG_ ## N2 ## _TYPE_SIZE) \ - MAKE_FIXED_TYPE_NODE (N1, long_long_, LONG_LONG_ ## N2 ## _TYPE_SIZE) + MAKE_FIXED_TYPE_NODE_WIDTH (N1, short_, SHORT_ ## N2 ## _TYPE_SIZE) \ + MAKE_FIXED_TYPE_NODE (N1, N2 ## _TYPE_SIZE) \ + MAKE_FIXED_TYPE_NODE_WIDTH (N1, long_, LONG_ ## N2 ## _TYPE_SIZE) \ + MAKE_FIXED_TYPE_NODE_WIDTH (N1, long_long_, LONG_LONG_ ## N2 ## _TYPE_SIZE) /* Make fixed-point mode nodes based on sat/non-sat and signed/unsigned. */ #define MAKE_FIXED_MODE_NODE(KIND,NAME,MODE) \ diff --git a/gcc/tree.h b/gcc/tree.h index c00ad54cf05..e6b9f9cf65e 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1586,6 +1586,9 @@ struct tree_vec GTY(()) /* In a CONSTRUCTOR node. */ #define CONSTRUCTOR_ELTS(NODE) (CONSTRUCTOR_CHECK (NODE)->constructor.elts) +#define CONSTRUCTOR_ELT(NODE,IDX) \ + (VEC_index (constructor_elt, CONSTRUCTOR_ELTS (NODE), IDX)) +#define CONSTRUCTOR_NELTS(NODE) (VEC_length (constructor_elt, CONSTRUCTOR_ELTS (NODE))) /* Iterate through the vector V of CONSTRUCTOR_ELT elements, yielding the value of each element (stored within VAL). IX must be a scratch variable @@ -4475,6 +4478,10 @@ extern int fields_length (const_tree); extern bool initializer_zerop (const_tree); +/* Given a CONSTRUCTOR CTOR, return the elements as a TREE_LIST. */ + +extern tree ctor_to_list (tree); + /* Examine CTOR to discover: * how many scalar fields are set to nonzero values, and place it in *P_NZ_ELTS; diff --git a/gcc/unwind-pe.h b/gcc/unwind-pe.h index 9c56af08486..6924e8c1732 100644 --- a/gcc/unwind-pe.h +++ b/gcc/unwind-pe.h @@ -71,6 +71,9 @@ include leb128. */ static unsigned int +size_of_encoded_value (unsigned char encoding) __attribute__ ((unused)); + +static unsigned int size_of_encoded_value (unsigned char encoding) { if (encoding == DW_EH_PE_omit) diff --git a/gcc/varray.c b/gcc/varray.c index 45330397e0e..6464a816652 100644 --- a/gcc/varray.c +++ b/gcc/varray.c @@ -49,13 +49,13 @@ static htab_t varray_hash; static hashval_t hash_descriptor (const void *p) { - const struct varray_descriptor *d = p; + const struct varray_descriptor *d = (const struct varray_descriptor *) p; return htab_hash_pointer (d->name); } static int eq_descriptor (const void *p1, const void *p2) { - const struct varray_descriptor *d = p1; + const struct varray_descriptor *d = (const struct varray_descriptor *) p1; return d->name == p2; } @@ -74,7 +74,7 @@ varray_descriptor (const char *name) 1); if (*slot) return *slot; - *slot = xcalloc (sizeof (**slot), 1); + *slot = XCNEW (struct varray_descriptor); (*slot)->name = name; return *slot; } diff --git a/gcc/vec.h b/gcc/vec.h index 10bdcc5f2e9..c07ee221584 100644 --- a/gcc/vec.h +++ b/gcc/vec.h @@ -480,6 +480,12 @@ typedef struct VEC(T,A) GTY \ VEC(T,B) base; \ } VEC(T,A) +#define VEC_TA(T,B,A) \ +typedef struct VEC(T,A) \ +{ \ + VEC(T,B) base; \ +} VEC(T,A) + /* Convert to base type. */ #define VEC_BASE(P) ((P) ? &(P)->base : 0) @@ -491,11 +497,11 @@ static inline void VEC_OP (T,must_be,integral_type) (void) \ } \ \ VEC_T(T,base); \ -VEC_TA_GTY(T,base,none,); \ +VEC_TA(T,base,none); \ DEF_VEC_FUNC_P(T) \ struct vec_swallow_trailing_semi #define DEF_VEC_ALLOC_I(T,A) \ -VEC_TA_GTY(T,base,A,); \ +VEC_TA(T,base,A); \ DEF_VEC_ALLOC_FUNC_I(T,A) \ struct vec_swallow_trailing_semi @@ -507,11 +513,11 @@ static inline void VEC_OP (T,must_be,pointer_type) (void) \ } \ \ VEC_T_GTY(T,base); \ -VEC_TA_GTY(T,base,none,); \ +VEC_TA(T,base,none); \ DEF_VEC_FUNC_P(T) \ struct vec_swallow_trailing_semi #define DEF_VEC_ALLOC_P(T,A) \ -VEC_TA_GTY(T,base,A,); \ +VEC_TA(T,base,A); \ DEF_VEC_ALLOC_FUNC_P(T,A) \ struct vec_swallow_trailing_semi @@ -797,11 +803,11 @@ static inline T *VEC_OP (T,A,safe_insert) \ /* Vector of object. */ #define DEF_VEC_O(T) \ VEC_T_GTY(T,base); \ -VEC_TA_GTY(T,base,none,); \ +VEC_TA(T,base,none); \ DEF_VEC_FUNC_O(T) \ struct vec_swallow_trailing_semi #define DEF_VEC_ALLOC_O(T,A) \ -VEC_TA_GTY(T,base,A,); \ +VEC_TA(T,base,A); \ DEF_VEC_ALLOC_FUNC_O(T,A) \ struct vec_swallow_trailing_semi diff --git a/include/ChangeLog b/include/ChangeLog index bf1af8da2cc..1636e982f79 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,14 @@ +2008-07-07 Joel Brobecker <brobecker@adacore.com> + + * safe-ctype.h: Add #include of ctype.h before redefining + the ctype.h macros. + +2008-07-04 Joel Brobecker <brobecker@adacore.com> + + * safe-ctype.h: Remove #error when detecting that ctype.h has been + included. Redefine the various macros provided by ctype.h as + undefined variables. + 2008-06-23 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> * libiberty.h (XALLOCA, XDUP, XALLOCAVEC, XDUPVEC, XALLOCAVAR, diff --git a/include/safe-ctype.h b/include/safe-ctype.h index e59b357ccfb..0266bf1aa26 100644 --- a/include/safe-ctype.h +++ b/include/safe-ctype.h @@ -35,10 +35,6 @@ Boston, MA 02110-1301, USA. */ #ifndef SAFE_CTYPE_H #define SAFE_CTYPE_H -#ifdef isalpha - #error "safe-ctype.h and ctype.h may not be used simultaneously" -#endif - /* Determine host character set. */ #define HOST_CHARSET_UNKNOWN 0 #define HOST_CHARSET_ASCII 1 @@ -116,4 +112,39 @@ extern const unsigned char _sch_tolower[256]; #define TOUPPER(c) _sch_toupper[(c) & 0xff] #define TOLOWER(c) _sch_tolower[(c) & 0xff] +/* Prevent the users of safe-ctype.h from accidently using the routines + from ctype.h. Initially, the approach was to produce an error when + detecting that ctype.h has been included. But this was causing + trouble as ctype.h might get indirectly included as a result of + including another system header (for instance gnulib's stdint.h). + So we include ctype.h here and then immediately redefine its macros. */ + +#include <ctype.h> +#undef isalpha +#define isalpha(c) do_not_use_isalpha_with_safe_ctype +#undef isalnum +#define isalnum(c) do_not_use_isalnum_with_safe_ctype +#undef iscntrl +#define iscntrl(c) do_not_use_iscntrl_with_safe_ctype +#undef isdigit +#define isdigit(c) do_not_use_isdigit_with_safe_ctype +#undef isgraph +#define isgraph(c) do_not_use_isgraph_with_safe_ctype +#undef islower +#define islower(c) do_not_use_islower_with_safe_ctype +#undef isprint +#define isprint(c) do_not_use_isprint_with_safe_ctype +#undef ispunct +#define ispunct(c) do_not_use_ispunct_with_safe_ctype +#undef isspace +#define isspace(c) do_not_use_isspace_with_safe_ctype +#undef isupper +#define isupper(c) do_not_use_isupper_with_safe_ctype +#undef isxdigit +#define isxdigit(c) do_not_use_isxdigit_with_safe_ctype +#undef toupper +#define toupper(c) do_not_use_toupper_with_safe_ctype +#undef tolower +#define tolower(c) do_not_use_tolower_with_safe_ctype + #endif /* SAFE_CTYPE_H */ diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 7f069414f7e..2d29a309566 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,9 @@ +2008-06-13 Andrew Haley <aph@redhat.com> + + PR preprocessor/33305 + * macro.c (replace_args): Print a warning for empty macro + arguments in C89 and C++. + 2008-06-17 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> * Makefile.in ($(srcdir)/aclocal.m4): Update dependencies. diff --git a/libcpp/macro.c b/libcpp/macro.c index 016754bc952..edc2856551a 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -1009,6 +1009,17 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg if (src->flags & PASTE_LEFT) paste_flag = dest - 1; } + else if (CPP_PEDANTIC (pfile) && ! macro->syshdr + && ! CPP_OPTION (pfile, c99) + && ! cpp_in_system_header (pfile)) + { + cpp_error (pfile, CPP_DL_PEDWARN, + "invoking macro %s argument %d: " + "empty macro arguments are undefined" + " in ISO C90 and ISO C++98", + NODE_NAME (node), + src->val.arg_no); + } /* Avoid paste on RHS (even case count == 0). */ if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT)) diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 0bcffffc56a..348afc5d227 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,85 @@ +2008-07-08 H.J. Lu <hongjiu.lu@intel.com> + + * config/i386/64/t-softfp-compat: Update comments. + +2008-07-07 H.J. Lu <hongjiu.lu@intel.com> + + * config/i386/64/_divtc3-compat.c: Moved to ... + * config/i386/64/_divtc3.c: Here. + + * config/i386/64/_multc3-compat.c: Moved to ... + * config/i386/64/_multc3.c: Here. + + * config/i386/64/_powitf2-compat.c: Moved to ... + * config/i386/64/_powitf2.c: Here. + + * config/i386/64/t-softfp-compat (libgcc2-tf-compats): Add + .c suffix instead of -compat.c. + +2008-07-05 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/32/sfp-machine.h (_FP_MUL_MEAT_S): Remove. + (_FP_MUL_MEAT_D): Ditto. + (_FP_DIV_MEAT_S): Ditto. + (_FP_DIV_MEAT_D): Ditto. + +2008-07-03 Richard Sandiford <rdsandiford@googlemail.com> + + * Makefile.in: Add support for __sync_* libgcc functions. + +2008-07-03 H.J. Lu <hongjiu.lu@intel.com> + + * shared-object.mk ($(base)_s$(objext)): Remove -DSHARED. + +2008-07-02 H.J. Lu <hongjiu.lu@intel.com> + + PR boostrap/36702 + * config.host: Only include 32bit t-fprules-softfp for Darwin/x86 + and Linux/x86. Include 64bit t-softfp-compat for Linux/x86. + + * config/i386/64/t-fprules-softfp: Moved to ... + * config/i386/64/t-softfp-compat: This. New. + +2008-07-02 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/32/sfp-machine.h (FP_HANDLE_EXCEPTIONS) [FP_EX_INVALID]: + Initialize f with 0.0. + +2008-07-02 H.J. Lu <hongjiu.lu@intel.com> + + PR target/36669 + * shared-object.mk ($(base)_s$(objext)): Add -DSHARED. + + * config/i386/64/_divtc3-compat.c: New. + * config/i386/64/_multc3-compat.c: Likewise. + * config/i386/64/_powitf2-compat.c: Likewise. + * config/i386/64/eqtf2.c: Likewise. + * config/i386/64/getf2.c: Likewise. + * config/i386/64/letf2.c: Likewise. + * config/i386/64/t-fprules-softfp: Likewise. + +2008-07-02 H.J. Lu <hongjiu.lu@intel.com> + + * config.host: Add i386/${host_address}/t-fprules-softfp to + tmake_file for i[34567]86-*-darwin*, x86_64-*-darwin*, + i[34567]86-*-linux*, x86_64-*-linux*. + + * configure.ac: Set host_address to 64 or 32 for x86. + * configure: Regenerated. + + * Makefile.in (config.status): Also depend on + $(srcdir)/config.host. + + * config/i386/32/t-fprules-softfp: New. + * config/i386/32/tf-signs.c: Likewise. + + * config/i386/64/sfp-machine.h: New. Moved from gcc. + +2008-07-02 H.J. Lu <hongjiu.lu@intel.com> + Uros Bizjak <ubizjak@gmail.com> + + * config/i386/32/sfp-machine.h: New. + 2008-06-26 Nathan Froyd <froydnj@codesourcery.com> * config/rs6000/t-ppccomm: Remove rules that conflict with @@ -73,8 +155,8 @@ Paolo Bonzini <bonzini@gnu.org> PR target/30572 - * Makefile.in: Use @shlib_slibdir@ substitution to get correct install name - on darwin. + * Makefile.in: Use @shlib_slibdir@ substitution to get + correct install name on darwin. * config/t-slibgcc-darwin: Use @shlib_slibdir@ for -install_name. 2007-12-15 Hans-Peter Nilsson <hp@axis.com> @@ -178,7 +260,7 @@ * config/i386/t-crtpc: New file. * config.host (i[34567]86-*-linux*): Add i386/t-crtpc to tm-file. - (x86_64-*-linux*): Ditto. + (x86_64-*-linux*): Ditto. 2007-02-30 Kai Tietz <kai.tietz@onevision.com> diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index 94b6440f011..5718a501830 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -138,7 +138,7 @@ config.h: stamp-h ; @true stamp-h: $(srcdir)/config.in config.status Makefile CONFIG_FILES= CONFIG_HEADERS=config.h:$(srcdir)/config.in $(SHELL) ./config.status -config.status: $(srcdir)/configure +config.status: $(srcdir)/configure $(srcdir)/config.host $(SHELL) ./config.status --recheck include $(gcc_objdir)/libgcc.mvars @@ -577,6 +577,54 @@ endif endif +ifeq ($(LIBGCC_SYNC),yes) +libgcc-sync-size-funcs := $(foreach op, add sub or and xor nand, \ + sync_fetch_and_$(op) \ + sync_$(op)_and_fetch) \ + sync_bool_compare_and_swap \ + sync_val_compare_and_swap \ + sync_lock_test_and_set + +libgcc-sync-size-funcs := $(foreach prefix, $(libgcc-sync-size-funcs), \ + $(foreach suffix, 1 2 4 8 16, \ + $(prefix)_$(suffix))) + +libgcc-sync-size-funcs-o = $(patsubst %,%$(objext),$(libgcc-sync-size-funcs)) +$(libgcc-sync-size-funcs-o): %$(objext): $(gcc_srcdir)/config/sync.c + $(gcc_compile) $(LIBGCC_SYNC_CFLAGS) \ + -DFN=`echo "$*" | sed 's/_[^_]*$$//'` \ + -DSIZE=`echo "$*" | sed 's/.*_//'` \ + -c $(gcc_srcdir)/config/sync.c $(vis_hide) +libgcc-objects += $(libgcc-sync-size-funcs-o) + +libgcc-sync-funcs := sync_synchronize + +libgcc-sync-funcs-o = $(patsubst %,%$(objext),$(libgcc-sync-funcs)) +$(libgcc-sync-funcs-o): %$(objext): $(gcc_srcdir)/config/sync.c + $(gcc_compile) $(LIBGCC_SYNC_CFLAGS) \ + -DL$* \ + -c $(gcc_srcdir)/config/sync.c $(vis_hide) +libgcc-objects += $(libgcc-sync-funcs-o) + +ifeq ($(enable_shared),yes) +libgcc-sync-size-funcs-s-o = $(patsubst %,%_s$(objext), \ + $(libgcc-sync-size-funcs)) +$(libgcc-sync-size-funcs-s-o): %_s$(objext): $(gcc_srcdir)/config/sync.c + $(gcc_s_compile) $(LIBGCC_SYNC_CFLAGS) \ + -DFN=`echo "$*" | sed 's/_[^_]*$$//'` \ + -DSIZE=`echo "$*" | sed 's/.*_//'` \ + -c $(gcc_srcdir)/config/sync.c +libgcc-s-objects += $(libgcc-sync-size-funcs-s-o) + +libgcc-sync-funcs-s-o = $(patsubst %,%_s$(objext),$(libgcc-sync-funcs)) +$(libgcc-sync-funcs-s-o): %_s$(objext): $(gcc_srcdir)/config/sync.c + $(gcc_s_compile) $(LIBGCC_SYNC_CFLAGS) \ + -DL$* \ + -c $(gcc_srcdir)/config/sync.c +libgcc-s-objects += $(libgcc-sync-funcs-s-o) +endif +endif + # Build fixed-point support. ifeq ($(fixed_point),yes) diff --git a/libgcc/config.host b/libgcc/config.host index da652de0ed8..93d1dbfacbb 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -578,3 +578,21 @@ i[34567]86-*-linux* | x86_64-*-linux*) tmake_file="${tmake_file} t-tls" ;; esac + +case ${host} in +i[34567]86-*-darwin* | x86_64-*-darwin* | \ + i[34567]86-*-linux* | x86_64-*-linux*) + if test "${host_address}" = 32; then + tmake_file="${tmake_file} i386/${host_address}/t-fprules-softfp" + fi + ;; +esac + +case ${host} in +i[34567]86-*-linux* | x86_64-*-linux*) + # Provide backward binary compatibility for 64bit Linux/x86. + if test "${host_address}" = 64; then + tmake_file="${tmake_file} i386/${host_address}/t-softfp-compat" + fi + ;; +esac diff --git a/libgcc/config/i386/32/sfp-machine.h b/libgcc/config/i386/32/sfp-machine.h new file mode 100644 index 00000000000..746ae7c1287 --- /dev/null +++ b/libgcc/config/i386/32/sfp-machine.h @@ -0,0 +1,209 @@ +#define _FP_W_TYPE_SIZE 32 +#define _FP_W_TYPE unsigned int +#define _FP_WS_TYPE signed int +#define _FP_I_TYPE int + +/* The type of the result of a floating point comparison. This must + match `__libgcc_cmp_return__' in GCC for the target. */ +typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); +#define CMPtype __gcc_CMPtype + +#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ + __asm__ ("add{l} {%11,%3|%3,%11}\n\t" \ + "adc{l} {%9,%2|%2,%9}\n\t" \ + "adc{l} {%7,%1|%1,%7}\n\t" \ + "adc{l} {%5,%0|%0,%5}" \ + : "=r" ((USItype) (r3)), \ + "=&r" ((USItype) (r2)), \ + "=&r" ((USItype) (r1)), \ + "=&r" ((USItype) (r0)) \ + : "%0" ((USItype) (x3)), \ + "g" ((USItype) (y3)), \ + "%1" ((USItype) (x2)), \ + "g" ((USItype) (y2)), \ + "%2" ((USItype) (x1)), \ + "g" ((USItype) (y1)), \ + "%3" ((USItype) (x0)), \ + "g" ((USItype) (y0))) +#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ + __asm__ ("add{l} {%8,%2|%2,%8}\n\t" \ + "adc{l} {%6,%1|%1,%6}\n\t" \ + "adc{l} {%4,%0|%0,%4}" \ + : "=r" ((USItype) (r2)), \ + "=&r" ((USItype) (r1)), \ + "=&r" ((USItype) (r0)) \ + : "%0" ((USItype) (x2)), \ + "g" ((USItype) (y2)), \ + "%1" ((USItype) (x1)), \ + "g" ((USItype) (y1)), \ + "%2" ((USItype) (x0)), \ + "g" ((USItype) (y0))) + +/* FIXME: Change last operand constraint + from "im" to "g" when reload works properly. */ +#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ + __asm__ ("sub{l} {%11,%3|%3,%11}\n\t" \ + "sbb{l} {%9,%2|%2,%9}\n\t" \ + "sbb{l} {%7,%1|%1,%7}\n\t" \ + "sbb{l} {%5,%0|%0,%5}" \ + : "=r" ((USItype) (r3)), \ + "=&r" ((USItype) (r2)), \ + "=&r" ((USItype) (r1)), \ + "=&r" ((USItype) (r0)) \ + : "0" ((USItype) (x3)), \ + "g" ((USItype) (y3)), \ + "1" ((USItype) (x2)), \ + "g" ((USItype) (y2)), \ + "2" ((USItype) (x1)), \ + "g" ((USItype) (y1)), \ + "3" ((USItype) (x0)), \ + "im" ((USItype) (y0))) +#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ + __asm__ ("sub{l} {%8,%2|%2,%8}\n\t" \ + "sbb{l} {%6,%1|%1,%6}\n\t" \ + "sbb{l} {%4,%0|%0,%4}" \ + : "=r" ((USItype) (r2)), \ + "=&r" ((USItype) (r1)), \ + "=&r" ((USItype) (r0)) \ + : "0" ((USItype) (x2)), \ + "g" ((USItype) (y2)), \ + "1" ((USItype) (x1)), \ + "g" ((USItype) (y1)), \ + "2" ((USItype) (x0)), \ + "g" ((USItype) (y0))) + + +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) + +#define _FP_NANFRAC_S _FP_QNANBIT_S +#define _FP_NANFRAC_D _FP_QNANBIT_D, 0 +/* Even if XFmode is 12byte, we have to pad it to + 16byte since soft-fp emulation is done in 16byte. */ +#define _FP_NANFRAC_E _FP_QNANBIT_E, 0, 0, 0 +#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0 +#define _FP_NANSIGN_S 1 +#define _FP_NANSIGN_D 1 +#define _FP_NANSIGN_E 1 +#define _FP_NANSIGN_Q 1 + +#define _FP_KEEPNANFRACP 1 + +/* Here is something Intel misdesigned: the specs don't define + the case where we have two NaNs with same mantissas, but + different sign. Different operations pick up different NaNs. */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if (_FP_FRAC_GT_##wc(X, Y) \ + || (_FP_FRAC_EQ_##wc(X,Y) && (OP == '+' || OP == '*'))) \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + else \ + { \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R,Y); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#define FP_EX_INVALID 0x01 +#define FP_EX_DENORM 0x02 +#define FP_EX_DIVZERO 0x04 +#define FP_EX_OVERFLOW 0x08 +#define FP_EX_UNDERFLOW 0x10 +#define FP_EX_INEXACT 0x20 + +struct fenv +{ + unsigned short int __control_word; + unsigned short int __unused1; + unsigned short int __status_word; + unsigned short int __unused2; + unsigned short int __tags; + unsigned short int __unused3; + unsigned int __eip; + unsigned short int __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short int __data_selector; + unsigned short int __unused5; +}; + +#define FP_HANDLE_EXCEPTIONS \ + do { \ + if (_fex & FP_EX_INVALID) \ + { \ + float f = 0.0; \ + __asm__ __volatile__ ("fdiv %0" : "+t" (f)); \ + __asm__ __volatile__ ("fwait"); \ + } \ + if (_fex & FP_EX_DIVZERO) \ + { \ + float f = 1.0, g = 0.0; \ + __asm__ __volatile__ ("fdivp" : "=t" (f) \ + : "0" (f), "u" (g) \ + : "st(1)"); \ + __asm__ __volatile__ ("fwait"); \ + } \ + if (_fex & FP_EX_OVERFLOW) \ + { \ + struct fenv temp; \ + __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ + temp.__status_word |= FP_EX_OVERFLOW; \ + __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ + __asm__ __volatile__ ("fwait"); \ + } \ + if (_fex & FP_EX_UNDERFLOW) \ + { \ + struct fenv temp; \ + __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ + temp.__status_word |= FP_EX_UNDERFLOW; \ + __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ + __asm__ __volatile__ ("fwait"); \ + } \ + if (_fex & FP_EX_INEXACT) \ + { \ + struct fenv temp; \ + __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ + temp.__status_word |= FP_EX_INEXACT; \ + __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ + __asm__ __volatile__ ("fwait"); \ + } \ + } while (0) + +#define FP_RND_NEAREST 0 +#define FP_RND_ZERO 0xc00 +#define FP_RND_PINF 0x800 +#define FP_RND_MINF 0x400 + +#define _FP_DECL_EX \ + unsigned short _fcw __attribute__ ((unused)) = FP_RND_NEAREST + +#define FP_INIT_ROUNDMODE \ + do { \ + __asm__ ("fnstcw %0" : "=m" (_fcw)); \ + } while (0) + +#define FP_ROUNDMODE (_fcw & 0xc00) + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +#define __BYTE_ORDER __LITTLE_ENDIAN + +/* Define ALIASNAME as a strong alias for NAME. */ +#if defined __MACH__ +/* Mach-O doesn't support aliasing. If these functions ever return + anything but CMPtype we need to revisit this... */ +#define strong_alias(name, aliasname) \ + CMPtype aliasname (TFtype a, TFtype b) { return name(a, b); } +#else +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); +#endif diff --git a/libgcc/config/i386/32/t-fprules-softfp b/libgcc/config/i386/32/t-fprules-softfp new file mode 100644 index 00000000000..8e7f3233b71 --- /dev/null +++ b/libgcc/config/i386/32/t-fprules-softfp @@ -0,0 +1,8 @@ +# Filter out TImode functions +tifunctions = fixtfti.c fixunstfti.c floattitf.c floatuntitf.c +tifunctions := $(addprefix $(gcc_srcdir)/config/soft-fp/, $(tifunctions)) + +LIB2ADD := $(filter-out $(tifunctions), $(LIB2ADD)) + +# Provide fallbacks for __builtin_copysignq and __builtin_fabsq. +LIB2ADD += $(srcdir)/config/i386/32/tf-signs.c diff --git a/libgcc/config/i386/32/tf-signs.c b/libgcc/config/i386/32/tf-signs.c new file mode 100644 index 00000000000..1b19b601269 --- /dev/null +++ b/libgcc/config/i386/32/tf-signs.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2008 Free Software Foundation, Inc. + +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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +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, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ + +union _FP_UNION_Q +{ + __float128 flt; + struct + { + unsigned long frac0 : 32; + unsigned long frac1 : 32; + unsigned long frac2 : 32; + unsigned long frac3 : 16; + unsigned exp : 15; + unsigned sign : 1; + } bits __attribute__((packed)); +}; + +__float128 +__copysigntf3 (__float128 a, __float128 b) +{ + union _FP_UNION_Q A, B; + + A.flt = a; + B.flt = b; + A.bits.sign = B.bits.sign; + + return A.flt; +} + +__float128 +__fabstf2 (__float128 a) +{ + union _FP_UNION_Q A; + + A.flt = a; + A.bits.sign = 0; + + return A.flt; +} diff --git a/libgcc/config/i386/64/_divtc3.c b/libgcc/config/i386/64/_divtc3.c new file mode 100644 index 00000000000..57ee350b7cd --- /dev/null +++ b/libgcc/config/i386/64/_divtc3.c @@ -0,0 +1,14 @@ +#ifdef SHARED +#define __divtc3 __divtc3_shared +#endif + +#define L_divtc3 +#include "libgcc2.c" + +#ifdef SHARED +#undef __divtc3 +extern __typeof__ (__divtc3_shared) __divtc3_compat __attribute__((alias ("__divtc3_shared"))); + +asm (".symver __divtc3_compat,__divtc3@GCC_4.0.0"); +asm (".symver __divtc3_shared,__divtc3@@GCC_4.3.0"); +#endif diff --git a/libgcc/config/i386/64/_multc3.c b/libgcc/config/i386/64/_multc3.c new file mode 100644 index 00000000000..49141a9384f --- /dev/null +++ b/libgcc/config/i386/64/_multc3.c @@ -0,0 +1,14 @@ +#ifdef SHARED +#define __multc3 __multc3_shared +#endif + +#define L_multc3 +#include "libgcc2.c" + +#ifdef SHARED +#undef __multc3 +extern __typeof__ (__multc3_shared) __multc3_compat __attribute__((alias ("__multc3_shared"))); + +asm (".symver __multc3_compat,__multc3@GCC_4.0.0"); +asm (".symver __multc3_shared,__multc3@@GCC_4.3.0"); +#endif diff --git a/libgcc/config/i386/64/_powitf2.c b/libgcc/config/i386/64/_powitf2.c new file mode 100644 index 00000000000..3bc3c904de7 --- /dev/null +++ b/libgcc/config/i386/64/_powitf2.c @@ -0,0 +1,14 @@ +#ifdef SHARED +#define __powitf2 __powitf2_shared +#endif + +#define L_powitf2 +#include "libgcc2.c" + +#ifdef SHARED +#undef __powitf2 +extern __typeof__ (__powitf2_shared) __powitf2_compat __attribute__((alias ("__powitf2_shared"))); + +asm (".symver __powitf2_compat,__powitf2@GCC_4.0.0"); +asm (".symver __powitf2_shared,__powitf2@@GCC_4.3.0"); +#endif diff --git a/libgcc/config/i386/64/eqtf2.c b/libgcc/config/i386/64/eqtf2.c new file mode 100644 index 00000000000..d9baba689be --- /dev/null +++ b/libgcc/config/i386/64/eqtf2.c @@ -0,0 +1,13 @@ +#ifdef SHARED +#define __netf2 __netf2_shared +#endif + +#include "config/soft-fp/eqtf2.c" + +#ifdef SHARED +#undef __netf2 +strong_alias (__netf2_shared, __netf2_compat); + +asm (".symver __netf2_compat,__netf2@GCC_3.0"); +asm (".symver __netf2_shared,__netf2@@GCC_4.3.0"); +#endif diff --git a/libgcc/config/i386/64/getf2.c b/libgcc/config/i386/64/getf2.c new file mode 100644 index 00000000000..30885cc0caf --- /dev/null +++ b/libgcc/config/i386/64/getf2.c @@ -0,0 +1,13 @@ +#ifdef SHARED +#define __gttf2 __gttf2_shared +#endif + +#include "config/soft-fp/getf2.c" + +#ifdef SHARED +#undef __gttf2 +strong_alias (__gttf2_shared, __gttf2_compat); + +asm (".symver __gttf2_compat,__gttf2@GCC_3.0"); +asm (".symver __gttf2_shared,__gttf2@@GCC_4.3.0"); +#endif diff --git a/libgcc/config/i386/64/letf2.c b/libgcc/config/i386/64/letf2.c new file mode 100644 index 00000000000..231f981c84c --- /dev/null +++ b/libgcc/config/i386/64/letf2.c @@ -0,0 +1,13 @@ +#ifdef SHARED +#define __lttf2 __lttf2_shared +#endif + +#include "config/soft-fp/letf2.c" + +#ifdef SHARED +#undef __lttf2 +strong_alias (__lttf2_shared, __lttf2_compat); + +asm (".symver __lttf2_compat,__lttf2@GCC_3.0"); +asm (".symver __lttf2_shared,__lttf2@@GCC_4.3.0"); +#endif diff --git a/libgcc/config/i386/64/sfp-machine.h b/libgcc/config/i386/64/sfp-machine.h new file mode 100644 index 00000000000..190e3cb0e81 --- /dev/null +++ b/libgcc/config/i386/64/sfp-machine.h @@ -0,0 +1,143 @@ +#define _FP_W_TYPE_SIZE 64 +#define _FP_W_TYPE unsigned long +#define _FP_WS_TYPE signed long +#define _FP_I_TYPE long + +typedef int TItype __attribute__ ((mode (TI))); +typedef unsigned int UTItype __attribute__ ((mode (TI))); + +#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype)) + +/* The type of the result of a floating point comparison. This must + match `__libgcc_cmp_return__' in GCC for the target. */ +typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); +#define CMPtype __gcc_CMPtype + +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) + +#define _FP_NANFRAC_S _FP_QNANBIT_S +#define _FP_NANFRAC_D _FP_QNANBIT_D +#define _FP_NANFRAC_E _FP_QNANBIT_E, 0 +#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0 +#define _FP_NANSIGN_S 1 +#define _FP_NANSIGN_D 1 +#define _FP_NANSIGN_E 1 +#define _FP_NANSIGN_Q 1 + +#define _FP_KEEPNANFRACP 1 + +/* Here is something Intel misdesigned: the specs don't define + the case where we have two NaNs with same mantissas, but + different sign. Different operations pick up different NaNs. */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if (_FP_FRAC_GT_##wc(X, Y) \ + || (_FP_FRAC_EQ_##wc(X,Y) && (OP == '+' || OP == '*'))) \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + else \ + { \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R,Y); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +#define FP_EX_INVALID 0x01 +#define FP_EX_DENORM 0x02 +#define FP_EX_DIVZERO 0x04 +#define FP_EX_OVERFLOW 0x08 +#define FP_EX_UNDERFLOW 0x10 +#define FP_EX_INEXACT 0x20 + +struct fenv +{ + unsigned short int __control_word; + unsigned short int __unused1; + unsigned short int __status_word; + unsigned short int __unused2; + unsigned short int __tags; + unsigned short int __unused3; + unsigned int __eip; + unsigned short int __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short int __data_selector; + unsigned short int __unused5; +}; + +#define FP_HANDLE_EXCEPTIONS \ + do { \ + if (_fex & FP_EX_INVALID) \ + { \ + float f = 0.0; \ + __asm__ __volatile__ ("divss %0, %0 " : : "x" (f)); \ + } \ + if (_fex & FP_EX_DIVZERO) \ + { \ + float f = 1.0, g = 0.0; \ + __asm__ __volatile__ ("divss %1, %0" : : "x" (f), "x" (g)); \ + } \ + if (_fex & FP_EX_OVERFLOW) \ + { \ + struct fenv temp; \ + __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ + temp.__status_word |= FP_EX_OVERFLOW; \ + __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ + __asm__ __volatile__ ("fwait"); \ + } \ + if (_fex & FP_EX_UNDERFLOW) \ + { \ + struct fenv temp; \ + __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ + temp.__status_word |= FP_EX_UNDERFLOW; \ + __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ + __asm__ __volatile__ ("fwait"); \ + } \ + if (_fex & FP_EX_INEXACT) \ + { \ + struct fenv temp; \ + __asm__ __volatile__ ("fnstenv %0" : "=m" (temp)); \ + temp.__status_word |= FP_EX_INEXACT; \ + __asm__ __volatile__ ("fldenv %0" : : "m" (temp)); \ + __asm__ __volatile__ ("fwait"); \ + } \ + } while (0) + +#define FP_RND_NEAREST 0 +#define FP_RND_ZERO 0xc00 +#define FP_RND_PINF 0x800 +#define FP_RND_MINF 0x400 + +#define _FP_DECL_EX \ + unsigned short _fcw __attribute__ ((unused)) = FP_RND_NEAREST + +#define FP_INIT_ROUNDMODE \ + do { \ + __asm__ ("fnstcw %0" : "=m" (_fcw)); \ + } while (0) + +#define FP_ROUNDMODE (_fcw & 0xc00) + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 + +#define __BYTE_ORDER __LITTLE_ENDIAN + +/* Define ALIASNAME as a strong alias for NAME. */ +#if defined __MACH__ +/* Mach-O doesn't support aliasing. If these functions ever return + anything but CMPtype we need to revisit this... */ +#define strong_alias(name, aliasname) \ + CMPtype aliasname (TFtype a, TFtype b) { return name(a, b); } +#else +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); +#endif diff --git a/libgcc/config/i386/64/t-softfp-compat b/libgcc/config/i386/64/t-softfp-compat new file mode 100644 index 00000000000..afaa526ae29 --- /dev/null +++ b/libgcc/config/i386/64/t-softfp-compat @@ -0,0 +1,15 @@ +# When TFmode was first added to x86-64 in gcc 4.3.0, some TFmode +# support functions got improper versions by accident. Here we +# correct the version and provide backward binary compatibility. + +# Filter out the following TFmode functions. +tf-compats = getf2.c letf2.c eqtf2.c +tf-functions := $(addprefix $(gcc_srcdir)/config/soft-fp/, $(tf-compats)) +LIB2ADD := $(filter-out $(tf-functions), $(LIB2ADD)) +LIB2ADD += $(addprefix $(srcdir)/config/i386/64/, $(tf-compats)) + +# Replace _divtc3, _multc3 and _powitf2. +libgcc2-tf-functions = _divtc3 _multc3 _powitf2 +LIB2FUNCS_EXCLUDE += $(libgcc2-tf-functions) +libgcc2-tf-compats = $(addsuffix .c, $(libgcc2-tf-functions)) +LIB2ADD += $(addprefix $(srcdir)/config/i386/64/, $(libgcc2-tf-compats)) diff --git a/libgcc/configure b/libgcc/configure index 80cbebbb426..75bf9034b1a 100644 --- a/libgcc/configure +++ b/libgcc/configure @@ -3402,6 +3402,21 @@ echo "${ECHO_T}$libgcc_cv_fixed_point" >&6 fixed_point=$libgcc_cv_fixed_point +# Check 32bit or 64bit for x86. +case ${host} in +i?86*-*-* | x86_64*-*-*) + cat > conftest.c <<EOF +#ifdef __x86_64__ +host_address=64 +#else +host_address=32 +#endif +EOF + eval `${CC-cc} -E conftest.c | grep host_address=` + rm -f conftest.c + ;; +esac + # Collect host-machine-specific information. . ${srcdir}/config.host diff --git a/libgcc/configure.ac b/libgcc/configure.ac index e3eb80a2148..1238d742450 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -153,6 +153,21 @@ AC_CACHE_CHECK([whether fixed-point is supported], [libgcc_cv_fixed_point], fixed_point=$libgcc_cv_fixed_point AC_SUBST(fixed_point) +# Check 32bit or 64bit for x86. +case ${host} in +i?86*-*-* | x86_64*-*-*) + cat > conftest.c <<EOF +#ifdef __x86_64__ +host_address=64 +#else +host_address=32 +#endif +EOF + eval `${CC-cc} -E conftest.c | grep host_address=` + rm -f conftest.c + ;; +esac + # Collect host-machine-specific information. . ${srcdir}/config.host diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 6e3a729fc7a..c845606c803 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,32 @@ +2008-07-07 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/36341 + PR fortran/34670 + * m4/matmul.m4: Add bounds checking. + * m4/matmull.m4: Likewise. + * generated/matmul_c10.c: Regenerated. + * generated/matmul_c16.c: Regenerated. + * generated/matmul_c4.c: Regenerated. + * generated/matmul_c8.c: Regenerated. + * generated/matmul_i1.c: Regenerated. + * generated/matmul_i16.c: Regenerated. + * generated/matmul_i2.c: Regenerated. + * generated/matmul_i4.c: Regenerated. + * generated/matmul_i8.c: Regenerated. + * generated/matmul_l16.c: Regenerated. + * generated/matmul_l4.c: Regenerated. + * generated/matmul_l8.c: Regenerated. + * generated/matmul_r10.c: Regenerated. + * generated/matmul_r16.c: Regenerated. + * generated/matmul_r4.c: Regenerated. + * generated/matmul_r8.c: Regenerated. + +2008-07-07 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * acinclude.m4 (LIBGFOR_CHECK_GTHR_DEFAULT): Fix configure cache + variable name. + * configure: Regenerate. + 2008-07-01 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR fortran/36676 diff --git a/libgfortran/acinclude.m4 b/libgfortran/acinclude.m4 index d1994b49d90..9f8ae54fab6 100644 --- a/libgfortran/acinclude.m4 +++ b/libgfortran/acinclude.m4 @@ -86,10 +86,10 @@ if (foovar > 10) return __sync_add_and_fetch (&foovar, -1);], dnl Check if threads are supported. AC_DEFUN([LIBGFOR_CHECK_GTHR_DEFAULT], [ AC_CACHE_CHECK([configured target thread model], - target_thread_file, [ -target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`]) + libgfor_cv_target_thread_file, [ +libgfor_cv_target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`]) - if test $target_thread_file != single; then + if test $libgfor_cv_target_thread_file != single; then AC_DEFINE(HAVE_GTHR_DEFAULT, 1, [Define if the compiler has a thread header that is non single.]) fi]) diff --git a/libgfortran/configure b/libgfortran/configure index 7f3b690f4b6..95a980d5e2c 100755 --- a/libgfortran/configure +++ b/libgfortran/configure @@ -33082,16 +33082,16 @@ _ACEOF echo "$as_me:$LINENO: checking configured target thread model" >&5 echo $ECHO_N "checking configured target thread model... $ECHO_C" >&6 -if test "${target_thread_file+set}" = set; then +if test "${libgfor_cv_target_thread_file+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else -target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'` +libgfor_cv_target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'` fi -echo "$as_me:$LINENO: result: $target_thread_file" >&5 -echo "${ECHO_T}$target_thread_file" >&6 +echo "$as_me:$LINENO: result: $libgfor_cv_target_thread_file" >&5 +echo "${ECHO_T}$libgfor_cv_target_thread_file" >&6 - if test $target_thread_file != single; then + if test $libgfor_cv_target_thread_file != single; then cat >>confdefs.h <<\_ACEOF #define HAVE_GTHR_DEFAULT 1 diff --git a/libgfortran/generated/matmul_c10.c b/libgfortran/generated/matmul_c10.c index 08c2044dd8b..0e378626f96 100644 --- a/libgfortran/generated/matmul_c10.c +++ b/libgfortran/generated/matmul_c10.c @@ -135,6 +135,47 @@ matmul_c10 (gfc_array_c10 * const restrict retarray, = internal_malloc_size (sizeof (GFC_COMPLEX_10) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_c16.c b/libgfortran/generated/matmul_c16.c index 6a2a6390967..34cc51dbd78 100644 --- a/libgfortran/generated/matmul_c16.c +++ b/libgfortran/generated/matmul_c16.c @@ -135,6 +135,47 @@ matmul_c16 (gfc_array_c16 * const restrict retarray, = internal_malloc_size (sizeof (GFC_COMPLEX_16) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_c4.c b/libgfortran/generated/matmul_c4.c index 6dcf6fea56a..fdfea1df955 100644 --- a/libgfortran/generated/matmul_c4.c +++ b/libgfortran/generated/matmul_c4.c @@ -135,6 +135,47 @@ matmul_c4 (gfc_array_c4 * const restrict retarray, = internal_malloc_size (sizeof (GFC_COMPLEX_4) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_c8.c b/libgfortran/generated/matmul_c8.c index 8bc619d879f..9d6694922f1 100644 --- a/libgfortran/generated/matmul_c8.c +++ b/libgfortran/generated/matmul_c8.c @@ -135,6 +135,47 @@ matmul_c8 (gfc_array_c8 * const restrict retarray, = internal_malloc_size (sizeof (GFC_COMPLEX_8) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_i1.c b/libgfortran/generated/matmul_i1.c index ca16ed40b2f..34fd7c51b78 100644 --- a/libgfortran/generated/matmul_i1.c +++ b/libgfortran/generated/matmul_i1.c @@ -135,6 +135,47 @@ matmul_i1 (gfc_array_i1 * const restrict retarray, = internal_malloc_size (sizeof (GFC_INTEGER_1) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_i16.c b/libgfortran/generated/matmul_i16.c index 33c62ae4152..0c7c5d8f396 100644 --- a/libgfortran/generated/matmul_i16.c +++ b/libgfortran/generated/matmul_i16.c @@ -135,6 +135,47 @@ matmul_i16 (gfc_array_i16 * const restrict retarray, = internal_malloc_size (sizeof (GFC_INTEGER_16) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_i2.c b/libgfortran/generated/matmul_i2.c index e3119acbd41..5d55847edce 100644 --- a/libgfortran/generated/matmul_i2.c +++ b/libgfortran/generated/matmul_i2.c @@ -135,6 +135,47 @@ matmul_i2 (gfc_array_i2 * const restrict retarray, = internal_malloc_size (sizeof (GFC_INTEGER_2) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_i4.c b/libgfortran/generated/matmul_i4.c index a1b8c50f051..a80f14940c8 100644 --- a/libgfortran/generated/matmul_i4.c +++ b/libgfortran/generated/matmul_i4.c @@ -135,6 +135,47 @@ matmul_i4 (gfc_array_i4 * const restrict retarray, = internal_malloc_size (sizeof (GFC_INTEGER_4) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_i8.c b/libgfortran/generated/matmul_i8.c index eee73ac88f0..91499c793e6 100644 --- a/libgfortran/generated/matmul_i8.c +++ b/libgfortran/generated/matmul_i8.c @@ -135,6 +135,47 @@ matmul_i8 (gfc_array_i8 * const restrict retarray, = internal_malloc_size (sizeof (GFC_INTEGER_8) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_l16.c b/libgfortran/generated/matmul_l16.c index b2b86ecfed1..b604edfb2ca 100644 --- a/libgfortran/generated/matmul_l16.c +++ b/libgfortran/generated/matmul_l16.c @@ -99,6 +99,47 @@ matmul_l16 (gfc_array_l16 * const restrict retarray, = internal_malloc_size (sizeof (GFC_LOGICAL_16) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } abase = a->data; a_kind = GFC_DESCRIPTOR_SIZE (a); diff --git a/libgfortran/generated/matmul_l4.c b/libgfortran/generated/matmul_l4.c index 9a6cb1d357d..5aed0fe2ba0 100644 --- a/libgfortran/generated/matmul_l4.c +++ b/libgfortran/generated/matmul_l4.c @@ -99,6 +99,47 @@ matmul_l4 (gfc_array_l4 * const restrict retarray, = internal_malloc_size (sizeof (GFC_LOGICAL_4) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } abase = a->data; a_kind = GFC_DESCRIPTOR_SIZE (a); diff --git a/libgfortran/generated/matmul_l8.c b/libgfortran/generated/matmul_l8.c index 7d4e35e82e3..26baad32136 100644 --- a/libgfortran/generated/matmul_l8.c +++ b/libgfortran/generated/matmul_l8.c @@ -99,6 +99,47 @@ matmul_l8 (gfc_array_l8 * const restrict retarray, = internal_malloc_size (sizeof (GFC_LOGICAL_8) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } abase = a->data; a_kind = GFC_DESCRIPTOR_SIZE (a); diff --git a/libgfortran/generated/matmul_r10.c b/libgfortran/generated/matmul_r10.c index 58dfe75814f..931e2bdc0f0 100644 --- a/libgfortran/generated/matmul_r10.c +++ b/libgfortran/generated/matmul_r10.c @@ -135,6 +135,47 @@ matmul_r10 (gfc_array_r10 * const restrict retarray, = internal_malloc_size (sizeof (GFC_REAL_10) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_r16.c b/libgfortran/generated/matmul_r16.c index a6a93be91fb..16ec175be0c 100644 --- a/libgfortran/generated/matmul_r16.c +++ b/libgfortran/generated/matmul_r16.c @@ -135,6 +135,47 @@ matmul_r16 (gfc_array_r16 * const restrict retarray, = internal_malloc_size (sizeof (GFC_REAL_16) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_r4.c b/libgfortran/generated/matmul_r4.c index 1154d41a33f..47d976415d0 100644 --- a/libgfortran/generated/matmul_r4.c +++ b/libgfortran/generated/matmul_r4.c @@ -135,6 +135,47 @@ matmul_r4 (gfc_array_r4 * const restrict retarray, = internal_malloc_size (sizeof (GFC_REAL_4) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/generated/matmul_r8.c b/libgfortran/generated/matmul_r8.c index 7bce2533b41..a359ffd8fd3 100644 --- a/libgfortran/generated/matmul_r8.c +++ b/libgfortran/generated/matmul_r8.c @@ -135,6 +135,47 @@ matmul_r8 (gfc_array_r8 * const restrict retarray, = internal_malloc_size (sizeof (GFC_REAL_8) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } if (GFC_DESCRIPTOR_RANK (retarray) == 1) diff --git a/libgfortran/m4/matmul.m4 b/libgfortran/m4/matmul.m4 index 181efa3b654..a43b430c2e3 100644 --- a/libgfortran/m4/matmul.m4 +++ b/libgfortran/m4/matmul.m4 @@ -136,6 +136,47 @@ matmul_'rtype_code` ('rtype` * const restrict retarray, = internal_malloc_size (sizeof ('rtype_name`) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } ' sinclude(`matmul_asm_'rtype_code`.m4')dnl ` diff --git a/libgfortran/m4/matmull.m4 b/libgfortran/m4/matmull.m4 index 54afa8a238e..800444564f7 100644 --- a/libgfortran/m4/matmull.m4 +++ b/libgfortran/m4/matmull.m4 @@ -100,6 +100,47 @@ matmul_'rtype_code` ('rtype` * const restrict retarray, = internal_malloc_size (sizeof ('rtype_name`) * size0 ((array_t *) retarray)); retarray->offset = 0; } + else if (compile_options.bounds_check) + { + index_type ret_extent, arg_extent; + + if (GFC_DESCRIPTOR_RANK (a) == 1) + { + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else if (GFC_DESCRIPTOR_RANK (b) == 1) + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic: is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + else + { + arg_extent = a->dim[0].ubound + 1 - a->dim[0].lbound; + ret_extent = retarray->dim[0].ubound + 1 - retarray->dim[0].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 1:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + + arg_extent = b->dim[1].ubound + 1 - b->dim[1].lbound; + ret_extent = retarray->dim[1].ubound + 1 - retarray->dim[1].lbound; + if (arg_extent != ret_extent) + runtime_error ("Incorrect extent in return array in" + " MATMUL intrinsic for dimension 2:" + " is %ld, should be %ld", + (long int) ret_extent, (long int) arg_extent); + } + } abase = a->data; a_kind = GFC_DESCRIPTOR_SIZE (a); diff --git a/libjava/ChangeLog b/libjava/ChangeLog index d0c1d068dbb..1caf0ef248b 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,16 @@ +2008-07-08 Matthias Klose <doko@ubuntu.com> + + * libtool-version: Bump soversion. + +2008-07-07 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * gnu/gcj/convert/make-trie.h: New. + * gnu/gcj/convert/gen-from-JIS.c: Include it. + * gnu/gcj/convert/make-trie.c: Likewise. + Fix typos and compiler warnings, diagnose a missing argument. + * Makefile.am (gen_from_JIS_SOURCES): Add gnu/gcj/convert/make-trie.h. + * Makefile.in: Regenerate. + 2008-06-30 Joshua Sumali <jsumali@redhat.com> Andrew Haley <aph@redhat.com> diff --git a/libjava/Makefile.am b/libjava/Makefile.am index c074f5752a0..ce6dbd201f7 100644 --- a/libjava/Makefile.am +++ b/libjava/Makefile.am @@ -727,7 +727,8 @@ noinst_PROGRAMS = gen-from-JIS gen_from_JIS_SOURCES = \ gnu/gcj/convert/gen-from-JIS.c \ - gnu/gcj/convert/make-trie.c + gnu/gcj/convert/make-trie.c \ + gnu/gcj/convert/make-trie.h gen_from_JIS_DEPENDENCIES = \ gnu/gcj/convert/JIS0201.h \ diff --git a/libjava/Makefile.in b/libjava/Makefile.in index ba487885efc..4aab2bcc835 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -471,7 +471,7 @@ gcj_dbtool_OBJECTS = $(am_gcj_dbtool_OBJECTS) am_gcjh_OBJECTS = gcjh_OBJECTS = $(am_gcjh_OBJECTS) am__gen_from_JIS_SOURCES_DIST = gnu/gcj/convert/gen-from-JIS.c \ - gnu/gcj/convert/make-trie.c + gnu/gcj/convert/make-trie.c gnu/gcj/convert/make-trie.h @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@am_gen_from_JIS_OBJECTS = gnu/gcj/convert/gen-from-JIS.$(OBJEXT) \ @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@ gnu/gcj/convert/make-trie.$(OBJEXT) gen_from_JIS_OBJECTS = $(am_gen_from_JIS_OBJECTS) @@ -8176,7 +8176,8 @@ extra_headers = java/lang/Object.h java/lang/Class.h install_data_local_split = 50 @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@gen_from_JIS_SOURCES = \ @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@ gnu/gcj/convert/gen-from-JIS.c \ -@MAINTAINER_MODE_TRUE@@NATIVE_TRUE@ gnu/gcj/convert/make-trie.c +@MAINTAINER_MODE_TRUE@@NATIVE_TRUE@ gnu/gcj/convert/make-trie.c \ +@MAINTAINER_MODE_TRUE@@NATIVE_TRUE@ gnu/gcj/convert/make-trie.h @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@gen_from_JIS_DEPENDENCIES = \ @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@ gnu/gcj/convert/JIS0201.h \ diff --git a/libjava/gnu/gcj/convert/gen-from-JIS.c b/libjava/gnu/gcj/convert/gen-from-JIS.c index 13745805ab8..d4cca14474e 100644 --- a/libjava/gnu/gcj/convert/gen-from-JIS.c +++ b/libjava/gnu/gcj/convert/gen-from-JIS.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999 Free Software Foundation +/* Copyright (C) 1999, 2008 Free Software Foundation This file is part of libgcj. @@ -7,6 +7,10 @@ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ #include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "make-trie.h" + struct chval { unsigned char b1; /* 1st byte */ @@ -59,6 +63,11 @@ main(int argc, char** argv) int low1_uc = 0xFFFF, high1_uc = 0; int low2_uc = 0xFFFF, high2_uc = 0; int i; int row, col; + if (argc < 2) + { + fprintf (stderr, "missing argument!\n"); + exit (-1); + } if (strcmp (argv[1], "JIS0208") == 0) chtab = chtab_0208; else if (strcmp (argv[1], "JIS0212") == 0) @@ -106,8 +115,7 @@ main(int argc, char** argv) fprintf(out,"/* This file is automatically generated from %s.TXT. */\n", argv[1]); - fprintf(out,"#pragma GCC java_exceptions\n", - argv[1]); + fprintf(out,"#pragma GCC java_exceptions\n"); fprintf(out, "unsigned short %s_to_Unicode[%d][%d] = {\n", argv[1], max1 - min1 + 1, max2 - min2 + 1); i = 0; @@ -156,7 +164,7 @@ main(int argc, char** argv) } else { - fprintf (stderr, "error - char table our of order!\n"); + fprintf (stderr, "error - char table out of order!\n"); exit (-1); } if (col != max2) diff --git a/libjava/gnu/gcj/convert/make-trie.c b/libjava/gnu/gcj/convert/make-trie.c index e89f70c5c9f..fe2d7892641 100644 --- a/libjava/gnu/gcj/convert/make-trie.c +++ b/libjava/gnu/gcj/convert/make-trie.c @@ -8,6 +8,7 @@ details. */ #include <stdio.h> #include <stdlib.h> +#include "make-trie.h" typedef struct trie_node { diff --git a/libjava/libtool-version b/libjava/libtool-version index 964dc4f4f01..db361f7b168 100644 --- a/libjava/libtool-version +++ b/libjava/libtool-version @@ -3,4 +3,4 @@ # a separate file so that version updates don't involve re-running # automake. # CURRENT:REVISION:AGE -9:0:0 +10:0:0 diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog index 44743b62b88..aabb9fd9eff 100644 --- a/libobjc/ChangeLog +++ b/libobjc/ChangeLog @@ -1,3 +1,7 @@ +2008-07-06 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * Makefile.in (install-info): New stub target. + 2008-06-17 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> * configure: Regenerate. diff --git a/libobjc/Makefile.in b/libobjc/Makefile.in index ee9f6a1f3c5..f9538af5cda 100644 --- a/libobjc/Makefile.in +++ b/libobjc/Makefile.in @@ -1,6 +1,6 @@ # Makefile for GNU Objective C runtime library. # Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, -# 2005, 2006 Free Software Foundation, Inc. +# 2005, 2006, 2007, 2008 Free Software Foundation, Inc. #This file is part of GCC. @@ -270,9 +270,10 @@ exception_gc.lo: exception.c doc: info dvi pdf html # No install-html or install-pdf support -.PHONY: install-html install-pdf +.PHONY: install-html install-pdf install-info install-html: install-pdf: +install-info: LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 42a56a22a93..da30a6a741e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,98 @@ +2008-07-08 Chris Fairles <chris.fairles@gmail.com> + + * include/std/type_traits: Add common_type. + * testsuite/20_util/common_type/requirements/ + explicit_instantiation.cc: New. + * testsuite/20_util/common_type/requirements/ + typedefs-1.cc: Likewise. + +2008-07-07 Paolo Carlini <paolo.carlini@oracle.com> + + * testsuite/lib/libstdc++.exp (check_v3_target_stdint): New. + * testsuite/lib/dg-options.exp (dg-require-cstdint): New. + * testsuite/20_util/ratio/cons/cons1.cc: Use it. + * testsuite/20_util/ratio/cons/cons_overflow.cc: Likewise. + * testsuite/20_util/ratio/operations/ops1.cc: Likewise. + * testsuite/20_util/ratio/operations/ops2.cc: Likewise. + * testsuite/20_util/ratio/operations/ops3.cc: Likewise. + * testsuite/20_util/ratio/operations/ops_overflow.cc: Likewise. + * testsuite/20_util/ratio/comparisons/comp1.cc: Likewise. + * testsuite/20_util/ratio/comparisons/comp2.cc: Likewise. + + * include/std/type_traits: Fix comment typo. + +2008-07-06 Roger Sayle <roger@eyesopen.com> + + * include/std/system_error (is_error_code_enum): Use identifier + _Tp instead of _T to avoid conflict with system macro on Darwin. + (is_error_condition_enum): Likewise. + +2008-07-05 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/postypes.h: Do not include <stdint.h>. + + * include/Makefile.am: Reorder. + +2008-07-05 Paolo Carlini <paolo.carlini@oracle.com> + + * include/std/ratio: Prefer __INTMAX_MAX__ to INTMAX_MAX (INTMAX_MIN). + +2008-07-05 Chris Fairles <chris.fairles@gmail.com> + + * include/std/ratio: Documentation for std::ratio class. Add conditions + to ratio_less to prevent overflow. + * testsuite/20_util/ratio/comparisons/comp2.cc: New. + * testsuite/20_util/ratio/cons/cons_overflow.cc: Update dg-error line + numbers. + +2008-07-04 Chris Fairles <chris.fairles@gmail.com> + + * include/std/ratio: New, per N2661. + * include/Makefile.am: Update. + * include/Makefile.in: Regenerate. + * testsuite/20_util/ratio/cons/cons1.cc: New. + * testsuite/20_util/ratio/cons/cons_overflow.cc: Likewise. + * testsuite/20_util/ratio/operations/ops1.cc: Likewise. + * testsuite/20_util/ratio/operations/ops2.cc: Likewise. + * testsuite/20_util/ratio/operations/ops3.cc: Likewise. + * testsuite/20_util/ratio/operations/ops_overflow.cc: Likewise. + * testsuite/20_util/ratio/comparisons/comp1.cc: Likewise. + +2008-07-04 Paolo Carlini <paolo.carlini@oracle.com> + + PR libstdc++/36616 + * testsuite/22_locale/time_put/put/char/4.cc: Just use es_ES instead. + * testsuite/22_locale/time_put/put/wchar_t/4.cc: Likewise. + +2008-07-03 Paolo Carlini <paolo.carlini@oracle.com> + + * testsuite/21_strings/basic_string/numeric_conversions/char/stof.cc: + Improve check on long double limits. + * testsuite/21_strings/basic_string/numeric_conversions/char/stod.cc: + Likewise. + * testsuite/21_strings/basic_string/numeric_conversions/wchar_t/ + stof.cc: Likewise. + * testsuite/21_strings/basic_string/numeric_conversions/wchar_t/ + stod.cc: Likewise. + +2008-07-03 Paolo Carlini <paolo.carlini@oracle.com> + + * libsupc++/Makefile.am: Add initializer_list to the headers. + * libsupc++/Makefile.in: Regenerate. + + * libsupc++/initializer_list: Minor cosmetic changes. + +2008-07-02 Jason Merrill <jason@redhat.com> + + * libsupc++/initializer_list: Uglify and wrap in + __GXX_EXPERIMENTAL_CXX0X__. + * include/bits/stl_map.h (insert(initializer_list)): Wrap. + +2008-07-02 Jason Merrill <jason@redhat.com> + + * libsupc++/initializer_list: New file. + * include/bits/stl_map.h (insert(initializer_list)): New method. + 2008-06-30 Alfred E. Heggestad <aeh@db.org> * include/backward/backward_warning.h: Fix typo. diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index a8f48c7d282..89ac735b218 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -54,6 +54,7 @@ std_headers = \ ${std_srcdir}/ostream \ ${std_srcdir}/queue \ ${std_srcdir}/random \ + ${std_srcdir}/ratio \ ${std_srcdir}/regex \ ${std_srcdir}/set \ ${std_srcdir}/sstream \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index ebd37c9020e..91374605548 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -310,6 +310,7 @@ std_headers = \ ${std_srcdir}/ostream \ ${std_srcdir}/queue \ ${std_srcdir}/random \ + ${std_srcdir}/ratio \ ${std_srcdir}/regex \ ${std_srcdir}/set \ ${std_srcdir}/sstream \ diff --git a/libstdc++-v3/include/bits/postypes.h b/libstdc++-v3/include/bits/postypes.h index 2870a8e59a1..5ead488fa48 100644 --- a/libstdc++-v3/include/bits/postypes.h +++ b/libstdc++-v3/include/bits/postypes.h @@ -46,10 +46,6 @@ #include <cwchar> // For mbstate_t -#ifdef _GLIBCXX_HAVE_STDINT_H -#include <stdint.h> // For int64_t -#endif - _GLIBCXX_BEGIN_NAMESPACE(std) // The types streamoff, streampos and wstreampos and the class @@ -68,7 +64,11 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * was typedef long. */ #ifdef _GLIBCXX_HAVE_INT64_T - typedef int64_t streamoff; +# if (__CHAR_BIT__ * __SIZEOF_LONG__ == 64) + typedef long streamoff; +# else + typedef long long streamoff; +# endif #else typedef long long streamoff; #endif diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h index a9486708ffe..cd85b9ab75d 100644 --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -64,6 +64,7 @@ #include <bits/functexcept.h> #include <bits/concept_check.h> +#include <initializer_list> _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) @@ -468,6 +469,20 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) insert(const value_type& __x) { return _M_t._M_insert_unique(__x); } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + /** + * @brief Attempts to insert a list of std::pairs into the %map. + * @param list A std::initializer_list<value_type> of pairs to be + * inserted. + * + * Complexity similar to that of the range constructor. + * + */ + void + insert(std::initializer_list<value_type> __list) + { insert (__list.begin(), __list.end()); } +#endif + /** * @brief Attempts to insert a std::pair into the %map. * @param position An iterator that serves as a hint as to where the diff --git a/libstdc++-v3/include/std/ratio b/libstdc++-v3/include/std/ratio new file mode 100644 index 00000000000..9980571f160 --- /dev/null +++ b/libstdc++-v3/include/std/ratio @@ -0,0 +1,288 @@ +// <ratio> -*- C++ -*- + +// Copyright (C) 2008 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +/** @file ratio + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_RATIO +#define _GLIBCXX_RATIO 1 + +#pragma GCC system_header + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +# include <c++0x_warning.h> +#else + +#include <type_traits> +#include <cstdint> + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + +namespace std +{ + template<intmax_t _Pn> + struct __static_sign + : integral_constant<intmax_t, (_Pn < 0) ? -1 : 1> + { }; + + template<intmax_t _Pn> + struct __static_abs + : integral_constant<intmax_t, _Pn * __static_sign<_Pn>::value> + { }; + + template<intmax_t _Pn, intmax_t _Qn> + struct __static_gcd; + + template<intmax_t _Pn, intmax_t _Qn> + struct __static_gcd + : __static_gcd<_Qn, (_Pn % _Qn)> + { }; + + template<intmax_t _Pn> + struct __static_gcd<_Pn, 0> + : integral_constant<intmax_t, __static_abs<_Pn>::value> + { }; + + template<intmax_t _Qn> + struct __static_gcd<0, _Qn> + : integral_constant<intmax_t, __static_abs<_Qn>::value> + { }; + + // Let c = 2^(half # of bits in an intmax_t) + // then we find a1, a0, b1, b0 s.t. N = a1*c + a0, M = b1*c + b0 + // The multiplication of N and M becomes, + // N * M = (a1 * b1)c^2 + (a0 * b1 + b0 * a1)c + a0 * b0 + // Multiplication is safe if each term and the sum of the terms + // is representable by intmax_t. + template<intmax_t _Pn, intmax_t _Qn> + struct __safe_multiply + { + private: + static const uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); + + static const uintmax_t __a0 = __static_abs<_Pn>::value % __c; + static const uintmax_t __a1 = __static_abs<_Pn>::value / __c; + static const uintmax_t __b0 = __static_abs<_Qn>::value % __c; + static const uintmax_t __b1 = __static_abs<_Qn>::value / __c; + + static_assert(__a1 == 0 || __b1 == 0, + "overflow in multiplication"); + static_assert(__a0 * __b1 + __b0 * __a1 < (__c >> 1), + "overflow in multiplication"); + static_assert(__b0 * __a0 <= __INTMAX_MAX__, + "overflow in multiplication"); + static_assert((__a0 * __b1 + __b0 * __a1) * __c <= + __INTMAX_MAX__ - __b0 * __a0, "overflow in multiplication"); + + public: + static const intmax_t value = _Pn * _Qn; + }; + + // Helpers for __safe_add + template<intmax_t _Pn, intmax_t _Qn, bool> + struct __add_overflow_check_impl + : integral_constant<bool, (_Pn <= __INTMAX_MAX__ - _Qn)> + { }; + + template<intmax_t _Pn, intmax_t _Qn> + struct __add_overflow_check_impl<_Pn, _Qn, false> + : integral_constant<bool, (_Pn >= -__INTMAX_MAX__ - _Qn)> + { }; + + template<intmax_t _Pn, intmax_t _Qn> + struct __add_overflow_check + : __add_overflow_check_impl<_Pn, _Qn, (_Qn >= 0)> + { }; + + template<intmax_t _Pn, intmax_t _Qn> + struct __safe_add + { + static_assert(__add_overflow_check<_Pn, _Qn>::value != 0, + "overflow in addition"); + + static const intmax_t value = _Pn + _Qn; + }; + + /** + * @brief Provides compile-time rational arithmetic. + * + * This class template represents any finite rational number with a + * numerator and denominator representable by compile-time constants of + * type intmax_t. The ratio is simplified when instantiated. + * + * For example: + * @code + * std::ratio<7,-21>::num == -1; + * std::ratio<7,-21>::den == 3; + * @endcode + * + */ + template<intmax_t _Num, intmax_t _Den = 1> + struct ratio + { + static_assert(_Den != 0, "denominator cannot be zero"); + static_assert(_Num >= -__INTMAX_MAX__ && _Den >= -__INTMAX_MAX__, + "out of range"); + + // Note: sign(N) * abs(N) == N + static const intmax_t num = + _Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value; + + static const intmax_t den = + __static_abs<_Den>::value / __static_gcd<_Num, _Den>::value; + }; + + template<intmax_t _Num, intmax_t _Den> + const intmax_t ratio<_Num, _Den>::num; + + template<intmax_t _Num, intmax_t _Den> + const intmax_t ratio<_Num, _Den>::den; + + template<typename _R1, typename _R2> + struct ratio_add + { + private: + static const intmax_t __gcd = + __static_gcd<_R1::den, _R2::den>::value; + + public: + typedef ratio< + __safe_add< + __safe_multiply<_R1::num, (_R2::den / __gcd)>::value, + __safe_multiply<_R2::num, (_R1::den / __gcd)>::value>::value, + __safe_multiply<_R1::den, (_R2::den / __gcd)>::value> type; + }; + + template<typename _R1, typename _R2> + struct ratio_subtract + { + typedef typename ratio_add< + _R1, + ratio<-_R2::num, _R2::den>>::type type; + }; + + template<typename _R1, typename _R2> + struct ratio_multiply + { + private: + static const intmax_t __gcd1 = + __static_gcd<_R1::num, _R2::den>::value; + static const intmax_t __gcd2 = + __static_gcd<_R2::num, _R1::den>::value; + + public: + typedef ratio< + __safe_multiply<(_R1::num / __gcd1), + (_R2::num / __gcd2)>::value, + __safe_multiply<(_R1::den / __gcd2), + (_R2::den / __gcd1)>::value> type; + }; + + template<typename _R1, typename _R2> + struct ratio_divide + { + static_assert(_R2::num != 0, "division by 0"); + + typedef typename ratio_multiply< + _R1, + ratio<_R2::den, _R2::num>>::type type; + }; + + template<typename _R1, typename _R2> + struct ratio_equal + : integral_constant<bool, _R1::num == _R2::num && _R1::den == _R2::den> + { }; + + template<typename _R1, typename _R2> + struct ratio_not_equal + : integral_constant<bool, !ratio_equal<_R1, _R2>::value> + { }; + + template<typename _R1, typename _R2> + struct __ratio_less_simple_impl + : integral_constant<bool, + (__safe_multiply<_R1::num, _R2::den>::value + < __safe_multiply<_R2::num, _R1::den>::value)> + { }; + + // If the denominators are equal or the signs differ, we can just compare + // numerators, otherwise fallback to the simple cross-multiply method. + template<typename _R1, typename _R2> + struct __ratio_less_impl + : conditional<(_R1::den == _R2::den + || (__static_sign<_R1::num>::value + != __static_sign<_R2::num>::value)), + integral_constant<bool, (_R1::num < _R2::num)>, + __ratio_less_simple_impl<_R1, _R2>>::type + { }; + + template<typename _R1, typename _R2> + struct ratio_less + : __ratio_less_impl<_R1, _R2>::type + { }; + + template<typename _R1, typename _R2> + struct ratio_less_equal + : integral_constant<bool, !ratio_less<_R2, _R1>::value> + { }; + + template<typename _R1, typename _R2> + struct ratio_greater + : integral_constant<bool, ratio_less<_R2, _R1>::value> + { }; + + template<typename _R1, typename _R2> + struct ratio_greater_equal + : integral_constant<bool, !ratio_less<_R1, _R2>::value> + { }; + + typedef ratio<1, 1000000000000000000> atto; + typedef ratio<1, 1000000000000000> femto; + typedef ratio<1, 1000000000000> pico; + typedef ratio<1, 1000000000> nano; + typedef ratio<1, 1000000> micro; + typedef ratio<1, 1000> milli; + typedef ratio<1, 100> centi; + typedef ratio<1, 10> deci; + typedef ratio< 10, 1> deca; + typedef ratio< 100, 1> hecto; + typedef ratio< 1000, 1> kilo; + typedef ratio< 1000000, 1> mega; + typedef ratio< 1000000000, 1> giga; + typedef ratio< 1000000000000, 1> tera; + typedef ratio< 1000000000000000, 1> peta; + typedef ratio< 1000000000000000000, 1> exa; +} + +#endif //_GLIBCXX_USE_C99_STDINT_TR1 + +#endif //__GXX_EXPERIMENTAL_CXX0X__ + +#endif //_GLIBCXX_RATIO diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error index 343eb6e83f7..b0585810663 100644 --- a/libstdc++-v3/include/std/system_error +++ b/libstdc++-v3/include/std/system_error @@ -53,7 +53,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) class system_error; /// is_error_code_enum - template<typename _T> + template<typename _Tp> struct is_error_code_enum : public false_type { }; template<> @@ -61,7 +61,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) : public true_type { }; /// is_error_condition_enum - template<typename _T> + template<typename _Tp> struct is_error_condition_enum : public false_type { }; template<> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 5fdc95ecad9..1a759187955 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -203,13 +203,13 @@ namespace std : public integral_constant<bool, __has_trivial_destructor(_Tp)> { }; - /// has_nothrow_default_destructor + /// has_nothrow_default_constructor template<typename _Tp> struct has_nothrow_default_constructor : public integral_constant<bool, __has_nothrow_constructor(_Tp)> { }; - /// has_nothrow_copy_destructor + /// has_nothrow_copy_constructor template<typename _Tp> struct has_nothrow_copy_constructor : public integral_constant<bool, __has_nothrow_copy(_Tp)> @@ -551,6 +551,41 @@ namespace std // Integral, but don't define. template<> struct make_signed<bool>; + + template<typename... _Tp> + struct common_type; + + template<typename _Tp> + struct common_type<_Tp> + { + static_assert(sizeof(_Tp) > 0, "must be complete type"); + typedef _Tp type; + }; + + template<typename _Tp, typename _Up> + class common_type<_Tp, _Up> + { + static_assert(sizeof(_Tp) > 0, "must be complete type"); + static_assert(sizeof(_Up) > 0, "must be complete type"); + + static _Tp&& __t(); + static _Up&& __u(); + + // HACK: Prevents optimization of ?: in the decltype + // expression when the condition is the literal, "true". + // See, PR36628. + static bool __true_or_false(); + + public: + typedef decltype(__true_or_false() ? __t() : __u()) type; + }; + + template<typename _Tp, typename _Up, typename... _Vp> + struct common_type<_Tp, _Up, _Vp...> + { + typedef typename + common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type; + }; } #endif // __GXX_EXPERIMENTAL_CXX0X__ diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am index 366efa27428..c0412f0b8ed 100644 --- a/libstdc++-v3/libsupc++/Makefile.am +++ b/libstdc++-v3/libsupc++/Makefile.am @@ -1,6 +1,6 @@ ## Makefile for the GNU C++ Support library. ## -## Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007 +## Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 ## Free Software Foundation, Inc. ## ## Process this file with automake to produce Makefile.in. @@ -33,7 +33,8 @@ noinst_LTLIBRARIES = libsupc++convenience.la headers = \ - exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h + exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \ + initializer_list if GLIBCXX_HOSTED c_sources = \ diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in index c484bd5e082..a1cc257f807 100644 --- a/libstdc++-v3/libsupc++/Makefile.in +++ b/libstdc++-v3/libsupc++/Makefile.in @@ -357,7 +357,8 @@ toolexeclib_LTLIBRARIES = libsupc++.la # 2) integrated libsupc++convenience.la that is to be a part of libstdc++.a noinst_LTLIBRARIES = libsupc++convenience.la headers = \ - exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h + exception new typeinfo cxxabi.h cxxabi-forced.h exception_defines.h \ + initializer_list @GLIBCXX_HOSTED_TRUE@c_sources = \ @GLIBCXX_HOSTED_TRUE@ cp-demangle.c diff --git a/libstdc++-v3/libsupc++/initializer_list b/libstdc++-v3/libsupc++/initializer_list new file mode 100644 index 00000000000..18fb15bc552 --- /dev/null +++ b/libstdc++-v3/libsupc++/initializer_list @@ -0,0 +1,72 @@ +// std::initializer_list support -*- C++ -*- + +// Copyright (C) 2008 Free Software Foundation, Inc. +// +// 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, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +#ifndef __CXX_INITIALIZER_LIST +#define __CXX_INITIALIZER_LIST + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + +#pragma GCC visibility push(default) + +#include <cstddef> + +namespace std +{ + template<class _E> + class initializer_list + { + const _E* __array; + size_t __len; + + // The compiler can call a private constructor. + initializer_list(const _E* __a, size_t __l) + : __array(__a), __len(__l) { } + + public: + initializer_list() + : __array(NULL), __len(0) { } + + // Number of elements. + size_t size() const + { return __len; } + + // First element. + const _E* begin() const + { return __array; } + + // One past the last element. + const _E* end() const + { return begin() + size(); } + }; +} + +#pragma GCC visibility pop +#endif // C++0x +#endif // __CXX_INITIALIZER_LIST diff --git a/libstdc++-v3/testsuite/20_util/common_type/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/common_type/requirements/explicit_instantiation.cc new file mode 100644 index 00000000000..fcc5b2adf30 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/common_type/requirements/explicit_instantiation.cc @@ -0,0 +1,46 @@ +// { dg-options "-std=gnu++0x" } +// { dg-do compile } + +// Copyright (C) 2008 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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 this library; see the file COPYING. If not, write to the Free +// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// NB: This file is for testing type_traits with NO OTHER INCLUDES. + +#include <type_traits> + +namespace std +{ + typedef int test_type1; + typedef int& test_type2; + typedef double test_type3; + typedef float test_type4; + + template struct common_type<test_type1>; + template struct common_type<test_type1, test_type2>; + template struct common_type<test_type1, test_type2, test_type3>; + template struct common_type<test_type1, test_type2, test_type3, test_type4>; +} diff --git a/libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-1.cc b/libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-1.cc new file mode 100644 index 00000000000..e4152e51d31 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/common_type/requirements/typedefs-1.cc @@ -0,0 +1,118 @@ +// { dg-options "-std=gnu++0x" } +// +// Copyright (C) 2008 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library 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. +// +// This library 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 this library; see the file COPYING. If not, write to the Free +// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +// USA. + +#include <type_traits> +#include <testsuite_hooks.h> + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +#define COMMON_TYPE_TEST_1(type1, uid) \ + typedef common_type<type1>::type JOIN(test_t,uid); \ + VERIFY( (is_same<JOIN(test_t,uid), JOIN(test_t,uid)>::value) ); \ + typedef common_type<const type1>::type JOIN(test_t,JOIN(uid,c)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,c)), \ + JOIN(test_t,JOIN(uid,c))>::value) ); \ + typedef common_type<volatile type1>::type JOIN(test_t,JOIN(uid,v)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,v)), \ + JOIN(test_t,JOIN(uid,v))>::value) ); \ + typedef common_type<const volatile type1>::type JOIN(test_t,JOIN(uid,cv)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,cv)), \ + JOIN(test_t,JOIN(uid,cv))>::value) ); \ + typedef common_type<type1 &>::type JOIN(test_t,JOIN(uid,l)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,l)), \ + JOIN(test_t,JOIN(uid,l))>::value) ); \ + typedef common_type<const type1 &>::type JOIN(test_t,JOIN(uid,lc)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,lc)), \ + JOIN(test_t,JOIN(uid,lc))>::value) ); \ + typedef common_type<volatile type1 &>::type JOIN(test_t,JOIN(uid,lv)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,lv)), \ + JOIN(test_t,JOIN(uid,lv))>::value) ); \ + typedef common_type<const volatile type1 &>::type JOIN(test_t,JOIN(uid,lcv)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,lcv)), \ + JOIN(test_t,JOIN(uid,lcv))>::value) ); \ + typedef common_type<type1 &&>::type JOIN(test_t,JOIN(uid,r)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,r)), \ + JOIN(test_t,JOIN(uid,r))>::value) ); \ + typedef common_type<const type1 &&>::type JOIN(test_t,JOIN(uid,rc)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,rc)), \ + JOIN(test_t,JOIN(uid,rc))>::value) ); \ + typedef common_type<volatile type1 &&>::type JOIN(test_t,JOIN(uid,rv)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,rv)), \ + JOIN(test_t,JOIN(uid,rv))>::value) ); \ + typedef common_type<const volatile type1 &&>::type JOIN(test_t,JOIN(uid,rcv)); \ + VERIFY( (is_same<JOIN(test_t,JOIN(uid,rcv)), \ + JOIN(test_t,JOIN(uid,rcv))>::value) ) + +struct A { }; +struct B : A { }; + +void test01() +{ + bool test __attribute__((unused)) = true; + using std::common_type; + using std::is_same; + + // Positive tests. + COMMON_TYPE_TEST_1(int, 1); + COMMON_TYPE_TEST_1(double, 2); + COMMON_TYPE_TEST_1(A, 3); + COMMON_TYPE_TEST_1(B, 4); +} + +#define COMMON_TYPE_TEST_2_IMPL(type1, type2, type3, uid) \ + typedef common_type<type1, type2>::type JOIN(JOIN(test, uid),_t1); \ + typedef common_type<type2, type1>::type JOIN(JOIN(test, uid),_t2); \ + VERIFY( (is_same<JOIN(JOIN(test, uid),_t1), type3>::value) ); \ + VERIFY( (is_same<JOIN(JOIN(test, uid),_t2), type3>::value) ) + +#define NO_CV + +#define COMMON_TYPE_TEST_2(cv_qual, type1, type2, type3, uid) \ + COMMON_TYPE_TEST_2_IMPL(cv_qual type1, type2, type3, uid); \ + COMMON_TYPE_TEST_2_IMPL(cv_qual type1 &, type2, type3, JOIN(uid,l)); \ + COMMON_TYPE_TEST_2_IMPL(cv_qual type1 &&, type2, type3, JOIN(uid,r)) + +#define COMMON_TYPE_TEST_ALL_2(type1, type2, type3, uid) \ + COMMON_TYPE_TEST_2(NO_CV, type1, type2, type3, uid); \ + COMMON_TYPE_TEST_2(const, type1, type2, type3, uid); \ + COMMON_TYPE_TEST_2(volatile, type1, type2, type3, uid); \ + COMMON_TYPE_TEST_2(const volatile, type1, type2, type3, uid) + +void test02() +{ + bool test __attribute__((unused)) = true; + using std::common_type; + using std::is_same; + + COMMON_TYPE_TEST_ALL_2(int, int, int, 1); + COMMON_TYPE_TEST_ALL_2(int, double, double, 2); + COMMON_TYPE_TEST_2(NO_CV, A, A, A, 3); + COMMON_TYPE_TEST_2(const, A, A, const A, 4); + COMMON_TYPE_TEST_2(NO_CV, B, A, A, 5); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/ratio/comparisons/comp1.cc b/libstdc++-v3/testsuite/20_util/ratio/comparisons/comp1.cc new file mode 100644 index 00000000000..c916b309998 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/ratio/comparisons/comp1.cc @@ -0,0 +1,82 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-cstdint "" } + +// Copyright (C) 2008 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <ratio> +#include <testsuite_hooks.h> + +void +test01() +{ + bool test __attribute__((unused)) = true; + + VERIFY(( std::ratio_equal<std::ratio<2,6>, std::ratio<1,3>>::value == 1 )); + VERIFY(( std::ratio_equal<std::ratio<2,6>, std::ratio<1,4>>::value == 0 )); + + VERIFY( (std::ratio_not_equal<std::ratio<2,6>, + std::ratio<1,3>>::value == 0) ); + VERIFY( (std::ratio_not_equal<std::ratio<2,6>, + std::ratio<1,4>>::value == 1) ); +} + +void +test02() +{ + bool test __attribute__((unused)) = true; + + VERIFY( (std::ratio_less<std::ratio<1,4>, std::ratio<1,3>>::value == 1) ); + VERIFY( (std::ratio_less<std::ratio<-1,3>, std::ratio<1,3>>::value == 1) ); + + VERIFY( (std::ratio_less<std::ratio<1,3>, std::ratio<1,4>>::value == 0) ); + VERIFY( (std::ratio_less<std::ratio<1,3>, std::ratio<-1,3>>::value == 0) ); + + VERIFY( (std::ratio_less_equal<std::ratio<-1,3>, + std::ratio<-1,3>>::value == 1) ); + VERIFY( ( std::ratio_less_equal<std::ratio<1,4>, + std::ratio<1,3>>::value == 1) ); + + VERIFY( (std::ratio_less_equal<std::ratio<1,4>, + std::ratio<-1,3>>::value == 0) ); + VERIFY( (std::ratio_less_equal<std::ratio<1,3>, + std::ratio<-1,3>>::value == 0) ); + + VERIFY( (std::ratio_greater<std::ratio<1,3>, std::ratio<1,4>>::value == 1) ); + VERIFY( (std::ratio_greater<std::ratio<1,3>, std::ratio<-1,3>>::value == 1) ); + + VERIFY( (std::ratio_greater<std::ratio<1,4>, std::ratio<1,3>>::value == 0) ); + VERIFY( (std::ratio_greater<std::ratio<-1,3>, std::ratio<1,3>>::value == 0) ); + + VERIFY( (std::ratio_greater_equal<std::ratio<1,3>, + std::ratio<1,3>>::value == 1) ); + VERIFY( (std::ratio_greater_equal<std::ratio<1,3>, + std::ratio<-1,3>>::value == 1) ); + + VERIFY( (std::ratio_greater_equal<std::ratio<-1,3>, + std::ratio<1,3>>::value == 0) ); + VERIFY( (std::ratio_greater_equal<std::ratio<1,4>, + std::ratio<1,3>>::value == 0) ); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/ratio/comparisons/comp2.cc b/libstdc++-v3/testsuite/20_util/ratio/comparisons/comp2.cc new file mode 100644 index 00000000000..56052e45328 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/ratio/comparisons/comp2.cc @@ -0,0 +1,51 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-cstdint "" } + +// Copyright (C) 2008 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <ratio> +#include <testsuite_hooks.h> + +static const std::intmax_t M = INTMAX_MAX; + +void +test01() +{ + bool test __attribute__((unused)) = true; + + // No overflow with same denominator + VERIFY( (std::ratio_less<std::ratio<M - 2, M>, + std::ratio<M - 1, M>>::value == 1) ); + + VERIFY( (std::ratio_less<std::ratio<M - 1, M>, + std::ratio<M - 2, M>>::value == 0) ); + + // No overflow if signs differ + VERIFY( (std::ratio_less<std::ratio<-M, M - 1>, + std::ratio<M - 1, M - 2>>::value == 1) ); + + VERIFY( (std::ratio_less<std::ratio<M - 1, M - 2>, + std::ratio<-M, M - 1>>::value == 0) ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/ratio/cons/cons1.cc b/libstdc++-v3/testsuite/20_util/ratio/cons/cons1.cc new file mode 100644 index 00000000000..84860699ac8 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/ratio/cons/cons1.cc @@ -0,0 +1,52 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-cstdint "" } + +// 2008-07-03 Chris Fairles <chris.fairles@gmail.com> + +// Copyright (C) 2008 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <ratio> +#include <testsuite_hooks.h> + +void +test01() +{ + bool test __attribute__((unused)) = true; + + std::ratio<1,3> r0; + std::ratio<2,6> r1; + std::ratio<2,-6> r2; + std::ratio<-2,6> r3; + + VERIFY( r0.num == 1 ); + VERIFY( r0.den == 3 ); + + VERIFY( r1.num == r0.num ); + VERIFY( r1.den == r0.den ); + VERIFY( r2.num == -r0.num ); + VERIFY( r2.den == r0.den ); + VERIFY( r3.num == -r0.num ); + VERIFY( r3.den == r0.den ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/ratio/cons/cons_overflow.cc b/libstdc++-v3/testsuite/20_util/ratio/cons/cons_overflow.cc new file mode 100644 index 00000000000..570ea6cbc7d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/ratio/cons/cons_overflow.cc @@ -0,0 +1,55 @@ +// { dg-do compile } +// { dg-options "-std=gnu++0x" } +// { dg-require-cstdint "" } + +// Copyright (C) 2008 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <ratio> + +void +test01() +{ + std::ratio<INTMAX_MAX, INTMAX_MAX> r1; + std::ratio<-INTMAX_MAX, INTMAX_MAX> r2; +} + +void +test02() +{ + std::ratio<INTMAX_MIN, 1> r1; +} + +void +test03() +{ + std::ratio<1, INTMAX_MIN> r1; +} + +void +test04() +{ + std::ratio<1,0> r1; +} + +// { dg-error "instantiated from here" "" { target *-*-* } 35 } +// { dg-error "instantiated from here" "" { target *-*-* } 41 } +// { dg-error "instantiated from here" "" { target *-*-* } 47 } +// { dg-error "denominator cannot be zero" "" { target *-*-* } 150 } +// { dg-error "out of range" "" { target *-*-* } 151 } +// { dg-excess-errors "In instantiation of" } diff --git a/libstdc++-v3/testsuite/20_util/ratio/operations/ops1.cc b/libstdc++-v3/testsuite/20_util/ratio/operations/ops1.cc new file mode 100644 index 00000000000..b05092dd8e9 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/ratio/operations/ops1.cc @@ -0,0 +1,75 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-cstdint "" } + +// 2008-07-03 Chris Fairles <chris.fairles@gmail.com> + +// Copyright (C) 2008 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <ratio> +#include <testsuite_hooks.h> + +void +test01() +{ + bool test __attribute__((unused)) = true; + + std::ratio_add<std::ratio<3,8>, std::ratio<5,12>>::type r; + + VERIFY( r.num == 19 ); + VERIFY( r.den == 24 ); +} + +void +test02() +{ + bool test __attribute__((unused)) = true; + std::ratio_subtract<std::ratio<3,8>, std::ratio<5,12>>::type r; + + VERIFY( r.num == -1 ); + VERIFY( r.den == 24 ); +} + +void +test03() +{ + bool test __attribute__((unused)) = true; + std::ratio_multiply<std::ratio<3,8>, std::ratio<5,12>>::type r; + + VERIFY( r.num == 5 ); + VERIFY( r.den == 32 ); +} + +void +test04() +{ + bool test __attribute__((unused)) = true; + std::ratio_divide<std::ratio<3,8>, std::ratio<5,12>>::type r; + + VERIFY( r.num == 9 ); + VERIFY( r.den == 10 ); +} + +int main() +{ + test01(); + test02(); + test03(); + test04(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/ratio/operations/ops2.cc b/libstdc++-v3/testsuite/20_util/ratio/operations/ops2.cc new file mode 100644 index 00000000000..3d3241f3128 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/ratio/operations/ops2.cc @@ -0,0 +1,73 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-cstdint "" } + +// 2008-07-03 Chris Fairles <chris.fairles@gmail.com> + +// Copyright (C) 2008 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <ratio> +#include <testsuite_hooks.h> + +typedef std::ratio<1, INTMAX_MAX> one_over_max; +typedef std::ratio<2, INTMAX_MAX> two_over_max; +typedef std::ratio<INTMAX_MAX, 1> max_over_one; +typedef std::ratio<INTMAX_MAX, 2> max_over_two; + +void +test01() +{ + bool test __attribute__((unused)) = true; + + std::ratio_add<one_over_max, one_over_max>::type r1; + + VERIFY( r1.num == two_over_max::num); + VERIFY( r1.den == two_over_max::den); + + std::ratio_add< + std::ratio<INTMAX_MAX / 2, INTMAX_MAX / 2>, + std::ratio<INTMAX_MAX / 2 , INTMAX_MAX / 2 + 1>>::type r2; + + VERIFY( r2.num == INTMAX_MAX ); + VERIFY( r2.den == (INTMAX_MAX / 2) + 1 ); +} + +void +test02() +{ + bool test __attribute__((unused)) = true; + + std::ratio_subtract<one_over_max, one_over_max>::type r1; + + VERIFY( r1.num == 0); + VERIFY( r1.den == 1); + + std::ratio_subtract< + std::ratio<INTMAX_MAX / 2, INTMAX_MAX / 2>, + std::ratio<INTMAX_MAX / 2 , INTMAX_MAX / 2 + 1>>::type r2; + + VERIFY( r2.num == 1 ); + VERIFY( r2.den == (INTMAX_MAX / 2) + 1 ); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/ratio/operations/ops3.cc b/libstdc++-v3/testsuite/20_util/ratio/operations/ops3.cc new file mode 100644 index 00000000000..2008275a216 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/ratio/operations/ops3.cc @@ -0,0 +1,72 @@ +// { dg-options "-std=gnu++0x" } +// { dg-require-cstdint "" } + +// 2008-07-03 Chris Fairles <chris.fairles@gmail.com> + +// Copyright (C) 2008 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <ratio> +#include <testsuite_hooks.h> + +void +test01() +{ + bool test __attribute__((unused)) = true; + + std::ratio_multiply< + std::ratio<2, INTMAX_MAX>, + std::ratio<INTMAX_MAX, 2>>::type r1; + + VERIFY( r1.num == 1 ); + VERIFY( r1.den == 1 ); + + std::ratio_multiply< + std::ratio<INTMAX_MAX, 2>, + std::ratio<2 , INTMAX_MAX - 1>>::type r2; + + VERIFY( r2.num == INTMAX_MAX ); + VERIFY( r2.den == INTMAX_MAX - 1 ); +} + +void +test02() +{ + bool test __attribute__((unused)) = true; + + std::ratio_divide< + std::ratio<INTMAX_MAX, 2>, + std::ratio<INTMAX_MAX, 2>>::type r1; + + VERIFY( r1.num == 1 ); + VERIFY( r1.den == 1 ); + + std::ratio_divide< + std::ratio<INTMAX_MAX-1, 2>, + std::ratio<INTMAX_MAX, 2>>::type r2; + + VERIFY( r2.num == INTMAX_MAX - 1 ); + VERIFY( r2.den == INTMAX_MAX ); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/ratio/operations/ops_overflow.cc b/libstdc++-v3/testsuite/20_util/ratio/operations/ops_overflow.cc new file mode 100644 index 00000000000..860f9f253b2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/ratio/operations/ops_overflow.cc @@ -0,0 +1,48 @@ +// { dg-do compile } +// { dg-options "-std=gnu++0x" } +// { dg-require-cstdint "" } + +// 2008-07-03 Chris Fairles <chris.fairles@gmail.com> + +// Copyright (C) 2008 Free Software Foundation +// +// This file is part of the GNU ISO C++ Library. This library 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. + +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, USA. + +#include <ratio> + +void +test01() +{ + std::ratio_add<std::ratio<INTMAX_MAX, 1>, std::ratio<1>>::type r1; +} + +void +test02() +{ + std::ratio_multiply<std::ratio<-INTMAX_MAX, 2>, std::ratio<3, 2>>::type r1; + std::ratio_multiply<std::ratio<INTMAX_MAX>, std::ratio<INTMAX_MAX>>::type r2; +} + +// { dg-error "instantiated from here" "" { target *-*-* } 30 } +// { dg-error "instantiated from here" "" { target *-*-* } 36 } +// { dg-error "instantiated from here" "" { target *-*-* } 37 } +// { dg-error "overflow in addition" "" { target *-*-* } 127 } +// { dg-error "overflow in multiplication" "" { target *-*-* } 95 } +// { dg-error "overflow in multiplication" "" { target *-*-* } 97 } +// { dg-error "overflow in multiplication" "" { target *-*-* } 99 } +// { dg-excess-errors "In instantiation of" } +// { dg-excess-errors "out of range" } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/stod.cc b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/stod.cc index f26a865684d..765c5a210ec 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/stod.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/stod.cc @@ -107,7 +107,8 @@ test01() } VERIFY( test ); - if (sizeof(double) < sizeof(long double)) + if ((numeric_limits<long double>::max() / 10000.0L) + > numeric_limits<double>::max()) { test = false; d1 = -1.0; diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/stof.cc b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/stof.cc index 515769e18f7..5645c0af9b8 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/stof.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/stof.cc @@ -107,7 +107,8 @@ test01() } VERIFY( test ); - if (sizeof(float) < sizeof(long double)) + if ((numeric_limits<long double>::max() / 10000.0L) + > numeric_limits<float>::max()) { test = false; f1 = -1.0f; diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/stod.cc b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/stod.cc index c1ebbb228d9..e494f4282ba 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/stod.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/stod.cc @@ -107,7 +107,8 @@ test01() } VERIFY( test ); - if (sizeof(double) < sizeof(long double)) + if ((numeric_limits<long double>::max() / 10000.0L) + > numeric_limits<double>::max()) { test = false; d1 = -1.0; diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/stof.cc b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/stof.cc index 6f443c8bf97..a6319f8e31e 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/stof.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/wchar_t/stof.cc @@ -107,7 +107,8 @@ test01() } VERIFY( test ); - if (sizeof(float) < sizeof(long double)) + if ((numeric_limits<long double>::max() / 10000.0L) + > numeric_limits<float>::max()) { test = false; f1 = -1.0f; diff --git a/libstdc++-v3/testsuite/22_locale/time_put/put/char/4.cc b/libstdc++-v3/testsuite/22_locale/time_put/put/char/4.cc index 2fb6cf6ae74..c28738d742b 100644 --- a/libstdc++-v3/testsuite/22_locale/time_put/put/char/4.cc +++ b/libstdc++-v3/testsuite/22_locale/time_put/put/char/4.cc @@ -39,30 +39,22 @@ void test04() // basic construction and sanity check locale loc_c = locale::classic(); - locale loc_fr = locale("fr_FR@euro"); - VERIFY( loc_fr != loc_c ); + locale loc_es = locale("es_ES"); + VERIFY( loc_es != loc_c ); // create an ostream-derived object, cache the time_put facet const string empty; ostringstream oss; - oss.imbue(loc_fr); + oss.imbue(loc_es); const time_put<char>& tim_put = use_facet<time_put<char> >(oss.getloc()); iterator_type os_it04 = tim_put.put(oss.rdbuf(), oss, '*', &time1, 'a'); string result4 = oss.str(); -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 7) - VERIFY( result4 == "dim." ); -#else - VERIFY( result4 == "dim" ); -#endif + VERIFY( result4 == "dom" ); - oss.str(empty); // "%d.%m.%Y" + oss.str(empty); // "%d/%m/%y" iterator_type os_it27 = tim_put.put(oss.rdbuf(), oss, '*', &time1, 'x'); - string result27 = oss.str(); -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 7) - VERIFY( result27 == "04/04/1971" ); -#else - VERIFY( result27 == "04.04.1971" ); -#endif + string result27 = oss.str(); // "04/04/71" + VERIFY( result27 == "04/04/71" ); oss.str(empty); // "%T" iterator_type os_it28 = tim_put.put(oss.rdbuf(), oss, '*', &time1, 'X'); @@ -71,12 +63,8 @@ void test04() oss.str(empty); iterator_type os_it37 = tim_put.put(oss.rdbuf(), oss, '*', &time1, 'x', 'E'); - string result37 = oss.str(); -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 7) - VERIFY( result37 == "04/04/1971" ); -#else - VERIFY( result37 == "04.04.1971" ); -#endif + string result37 = oss.str(); // "04/04/71" + VERIFY( result37 == "04/04/71" ); oss.str(empty); iterator_type os_it38 = tim_put.put(oss.rdbuf(), oss, '*', &time1, 'X', 'E'); diff --git a/libstdc++-v3/testsuite/22_locale/time_put/put/wchar_t/4.cc b/libstdc++-v3/testsuite/22_locale/time_put/put/wchar_t/4.cc index 09920521945..c3d312da7d7 100644 --- a/libstdc++-v3/testsuite/22_locale/time_put/put/wchar_t/4.cc +++ b/libstdc++-v3/testsuite/22_locale/time_put/put/wchar_t/4.cc @@ -39,30 +39,22 @@ void test04() // basic construction and sanity check locale loc_c = locale::classic(); - locale loc_fr = locale("fr_FR@euro"); - VERIFY( loc_fr != loc_c ); + locale loc_es = locale("es_ES"); + VERIFY( loc_es != loc_c ); // create an ostream-derived object, cache the time_put facet const wstring empty; wostringstream oss; - oss.imbue(loc_fr); + oss.imbue(loc_es); const time_put<wchar_t>& tim_put = use_facet<time_put<wchar_t> >(oss.getloc()); iterator_type os_it04 = tim_put.put(oss.rdbuf(), oss, L'*', &time1, 'a'); wstring result4 = oss.str(); -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 7) - VERIFY( result4 == L"dim." ); -#else - VERIFY( result4 == L"dim" ); -#endif + VERIFY( result4 == L"dom" ); - oss.str(empty); // "%d.%m.%Y" + oss.str(empty); // "%d/%m/%y" iterator_type os_it27 = tim_put.put(oss.rdbuf(), oss, L'*', &time1, 'x'); - wstring result27 = oss.str(); -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 7) - VERIFY( result27 == L"04/04/1971" ); -#else - VERIFY( result27 == L"04.04.1971" ); -#endif + wstring result27 = oss.str(); // "04/04/71" + VERIFY( result27 == L"04/04/71" ); oss.str(empty); // "%T" iterator_type os_it28 = tim_put.put(oss.rdbuf(), oss, L'*', &time1, 'X'); @@ -71,12 +63,8 @@ void test04() oss.str(empty); iterator_type os_it37 = tim_put.put(oss.rdbuf(), oss, L'*', &time1, 'x', 'E'); - wstring result37 = oss.str(); -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 7) - VERIFY( result37 == L"04/04/1971" ); -#else - VERIFY( result37 == L"04.04.1971" ); -#endif + wstring result37 = oss.str(); // "04/04/71" + VERIFY( result37 == L"04/04/71" ); oss.str(empty); iterator_type os_it38 = tim_put.put(oss.rdbuf(), oss, L'*', &time1, 'X', 'E'); diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp index 327b691fc0f..e2d22ae598b 100644 --- a/libstdc++-v3/testsuite/lib/dg-options.exp +++ b/libstdc++-v3/testsuite/lib/dg-options.exp @@ -88,3 +88,12 @@ proc dg-require-rvalref { args } { } return } + +proc dg-require-cstdint { args } { + if { ![ check_v3_target_cstdint ] } { + upvar dg-do-what dg-do-what + set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"] + return + } + return +} diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp index d6b372b80ef..d8c168defac 100644 --- a/libstdc++-v3/testsuite/lib/libstdc++.exp +++ b/libstdc++-v3/testsuite/lib/libstdc++.exp @@ -1,6 +1,6 @@ # libstdc++ "tool init file" for DejaGNU -# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 +# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 # Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify @@ -939,7 +939,7 @@ proc check_v3_target_debug_mode { } { } else { set et_debug_mode 0 - # Set up, compile, and execute a C++ test program that depends + # Set up and compile a C++ test program that depends # on debug mode working. set src debug_mode[pid].cc set exe debug_mode[pid].exe @@ -993,7 +993,7 @@ proc check_v3_target_parallel_mode { } { } else { set et_parallel_mode 0 - # Set up, compile, and execute a C++ test program that depends + # Set up and compile a C++ test program that depends # on parallel mode working. set src parallel_mode[pid].cc set exe parallel_mode[pid].exe @@ -1021,3 +1021,61 @@ proc check_v3_target_parallel_mode { } { verbose "check_v3_target_parallel_mode: $et_parallel_mode" 2 return $et_parallel_mode } + +proc check_v3_target_cstdint { } { + global cxxflags + global DEFAULT_CXXFLAGS + global et_cstdint + + global tool + + if { ![info exists et_cstdint_target_name] } { + set et_cstdint_target_name "" + } + + # If the target has changed since we set the cached value, clear it. + set current_target [current_target_name] + if { $current_target != $et_cstdint_target_name } { + verbose "check_v3_target_cstdint: `$et_cstdint_target_name'" 2 + set et_cstdint_target_name $current_target + if [info exists et_cstdint] { + verbose "check_v3_target_cstdint: removing cached result" 2 + unset et_cstdint + } + } + + if [info exists et_cstdint] { + verbose "check_v3_target_cstdint: using cached result" 2 + } else { + set et_cstdint 0 + + # Set up and compile a C++0x test program that depends + # on the C99 stdint facilities to be available. + set src cstdint[pid].cc + set exe cstdint[pid].exe + + set f [open $src "w"] + puts $f "#include <cstdint>" + puts $f "int main()" + puts $f "#ifdef _GLIBCXX_USE_C99_STDINT_TR1" + puts $f "{ return 0; }" + puts $f "#endif" + close $f + + set cxxflags_saved $cxxflags + set cxxflags "$cxxflags $DEFAULT_CXXFLAGS -std=gnu++0x -Werror" + + set lines [v3_target_compile $src $exe executable ""] + set cxxflags $cxxflags_saved + file delete $src + + if [string match "" $lines] { + # No error message, compilation succeeded. + set et_cstdint 1 + } else { + verbose "check_v3_target_cstdint: compilation failed" 2 + } + } + verbose "check_v3_target_cstdint: $et_cstdint" 2 + return $et_cstdint +} diff --git a/maintainer-scripts/ChangeLog b/maintainer-scripts/ChangeLog index aaa34965ac9..f246a012cf5 100644 --- a/maintainer-scripts/ChangeLog +++ b/maintainer-scripts/ChangeLog @@ -1,3 +1,13 @@ +2008-07-04 Joseph Myers <joseph@codesourcery.com> + + * crontab: Remove 4.1 snapshots job. + * update_version: Remove. + * gcc_release: Remove support for g77 and release status in + version.c. + * update_version_svn: Ignore 4.1 branch. Remove support for + updating files other than DATESTAMP. + * update_web_docs_svn: Remove support for g77 manual. + 2008-02-18 Jakub Jelinek <jakub@redhat.com> * crontab: Add 4.3 branch. Set trunk to 4.4. diff --git a/maintainer-scripts/crontab b/maintainer-scripts/crontab index 6ccf62db2ae..091c24d8249 100644 --- a/maintainer-scripts/crontab +++ b/maintainer-scripts/crontab @@ -1,7 +1,6 @@ 16 0 * * * sh /home/gccadmin/scripts/update_version_svn 50 0 * * * sh /home/gccadmin/scripts/update_web_docs_svn 55 0 * * * sh /home/gccadmin/scripts/update_web_docs_libstdcxx_svn -32 22 * * 1 sh /home/gccadmin/scripts/gcc_release -s 4.1:branches/gcc-4_1-branch -l -d /sourceware/snapshot-tmp/gcc all 32 22 * * 3 sh /home/gccadmin/scripts/gcc_release -s 4.2:branches/gcc-4_2-branch -l -d /sourceware/snapshot-tmp/gcc all 32 22 * * 4 sh /home/gccadmin/scripts/gcc_release -s 4.3:branches/gcc-4_3-branch -l -d /sourceware/snapshot-tmp/gcc all 32 22 * * 5 sh /home/gccadmin/scripts/gcc_release -s 4.4:trunk -l -d /sourceware/snapshot-tmp/gcc all diff --git a/maintainer-scripts/gcc_release b/maintainer-scripts/gcc_release index bacb25b0ceb..467ec4e4aca 100755 --- a/maintainer-scripts/gcc_release +++ b/maintainer-scripts/gcc_release @@ -139,25 +139,14 @@ EOF fi done - # Update gcc/DEV-PHASE if it exists, otherwise gcc/version.c. - - if [ -f ${SOURCE_DIRECTORY}/gcc/DEV-PHASE ]; then - [ `cat ${SOURCE_DIRECTORY}/gcc/BASE-VER` = ${RELEASE} ] || \ - error "Release number ${RELEASE} does not match BASE-VER" - (changedir ${SOURCE_DIRECTORY}/gcc && \ - : > DEV-PHASE && \ - ${SVN} -q ci -m 'Mark as release' DEV-PHASE) || \ - error "Could not update DEV-PHASE" - else - for x in gcc/version.c; do - y=`basename ${x}` - (changedir `dirname ${SOURCE_DIRECTORY}/${x}` && \ - sed -e 's|version_string\[\] = \".*\"|version_string\[\] = \"'${RELEASE}'\"|g' < ${y} > ${y}.new && \ - mv ${y}.new ${y} && \ - ${SVN} -q ci -m 'Update version' ${y}) || \ - error "Could not update ${x}" - done - fi + # Update gcc/DEV-PHASE. + + [ `cat ${SOURCE_DIRECTORY}/gcc/BASE-VER` = ${RELEASE} ] || \ + error "Release number ${RELEASE} does not match BASE-VER" + (changedir ${SOURCE_DIRECTORY}/gcc && \ + : > DEV-PHASE && \ + ${SVN} -q ci -m 'Mark as release' DEV-PHASE) || \ + error "Could not update DEV-PHASE" # Make sure we tag the sources for a final release. TAG="tags/gcc_`echo ${RELEASE} | tr . _`_release" @@ -297,7 +286,6 @@ build_tarfiles() { # Now, build one for each of the languages. maybe_build_tarfile gcc-ada-${RELEASE} ${ADA_DIRS} maybe_build_tarfile gcc-g++-${RELEASE} ${CPLUSPLUS_DIRS} - maybe_build_tarfile gcc-g77-${RELEASE} ${FORTRAN_DIRS} maybe_build_tarfile gcc-fortran-${RELEASE} ${FORTRAN95_DIRS} maybe_build_tarfile gcc-java-${RELEASE} ${JAVA_DIRS} maybe_build_tarfile gcc-objc-${RELEASE} ${OBJECTIVEC_DIRS} @@ -305,7 +293,7 @@ build_tarfiles() { # The core is everything else. EXCLUDES="" - for x in ${ADA_DIRS} ${CPLUSPLUS_DIRS} ${FORTRAN_DIRS} ${FORTRAN95_DIRS}\ + for x in ${ADA_DIRS} ${CPLUSPLUS_DIRS} ${FORTRAN95_DIRS}\ ${JAVA_DIRS} ${OBJECTIVEC_DIRS} ${TESTSUITE_DIRS}; do EXCLUDES="${EXCLUDES} --exclude $x" done @@ -328,7 +316,7 @@ build_diffs() { old_vers=${old_file%.tar.bz2} old_vers=${old_vers#gcc-} inform "Building diffs against version $old_vers" - for f in gcc gcc-ada gcc-g++ gcc-g77 gcc-fortran gcc-java gcc-objc gcc-testsuite gcc-core; do + for f in gcc gcc-ada gcc-g++ gcc-fortran gcc-java gcc-objc gcc-testsuite gcc-core; do old_tar=${old_dir}/${f}-${old_vers}.tar.bz2 new_tar=${WORKING_DIRECTORY}/${f}-${RELEASE}.tar.bz2 if [ ! -e $old_tar ]; then @@ -453,7 +441,6 @@ with the following options: <code>"svn://gcc.gnu.org/svn/gcc/${SVNBRANCH} revisi snapshot_print gcc-ada-${RELEASE}.tar.bz2 "Ada front end and runtime" snapshot_print gcc-fortran-${RELEASE}.tar.bz2 "Fortran front end and runtime" snapshot_print gcc-g++-${RELEASE}.tar.bz2 "C++ front end and runtime" - snapshot_print gcc-g77-${RELEASE}.tar.bz2 "Fortran 77 front end and runtime" snapshot_print gcc-java-${RELEASE}.tar.bz2 "Java front end and runtime" snapshot_print gcc-objc-${RELEASE}.tar.bz2 "Objective-C front end and runtime" snapshot_print gcc-testsuite-${RELEASE}.tar.bz2 "The GCC testsuite" @@ -560,7 +547,6 @@ SOURCE_DIRECTORY="" # tar files. These are all relative to the top of the source tree. ADA_DIRS="gcc/ada libada gnattools" CPLUSPLUS_DIRS="gcc/cp libstdc++-v3" -FORTRAN_DIRS="gcc/f libf2c" FORTRAN95_DIRS="gcc/fortran libgfortran" JAVA_DIRS="gcc/java libjava libffi fastjar zlib boehm-gc" OBJECTIVEC_DIRS="gcc/objc gcc/objcp libobjc" @@ -707,7 +693,6 @@ SOURCE_DIRECTORY="${WORKING_DIRECTORY}/gcc-${RELEASE}" # relative to the WORKING_DIRECTORY. ADA_DIRS=`adjust_dirs ${ADA_DIRS}` CPLUSPLUS_DIRS=`adjust_dirs ${CPLUSPLUS_DIRS}` -FORTRAN_DIRS=`adjust_dirs ${FORTRAN_DIRS}` FORTRAN95_DIRS=`adjust_dirs ${FORTRAN95_DIRS}` JAVA_DIRS=`adjust_dirs ${JAVA_DIRS}` OBJECTIVEC_DIRS=`adjust_dirs ${OBJECTIVEC_DIRS}` diff --git a/maintainer-scripts/update_version b/maintainer-scripts/update_version deleted file mode 100755 index 2217052332c..00000000000 --- a/maintainer-scripts/update_version +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/sh -# -# Update the current version date in all files in the tree containing -# it. Consider all release branches except those matching the regular -# expression in $IGNORE_BRANCHES, and also consider those branches listed -# in $ADD_BRANCHES. - -CVSROOT=${CVSROOT:-/cvs/gcc} -IGNORE_BRANCHES='gcc-(2_95|3_0|3_1|3_2|3_3)-branch' -ADD_BRANCHES='HEAD autovect-branch dfp-branch' - -# Run this from /tmp. -export CVSROOT -/bin/rm -rf /tmp/$$ -/bin/mkdir /tmp/$$ -cd /tmp/$$ - -# The path to cvs. -CVS=${CVS:-/usr/local/bin/cvs} - -# Compute the branches which we should update. -$CVS co gcc/ChangeLog -BRANCHES=`$CVS status -v gcc/ChangeLog \ - | awk '{print $1;}' \ - | egrep 'gcc-[0-9]+_[0-9]+-branch$' \ - | egrep -v $IGNORE_BRANCHES` -# Always update the mainline. -BRANCHES="${BRANCHES} ${ADD_BRANCHES}" - -# ARGS is passed to 'cvs co' -CURR_DATE=`/bin/date +"%Y%m%d"` - -# version is contained within a char* -textstring_FILES="gcc/gcc/version.c" - -# version is contained within a #define -cppdefine_FILES="gcc/libstdc++-v3/include/bits/c++config" - -# version is all there is -datestamp_FILES="gcc/gcc/DATESTAMP" - -FILES="$textstring_FILES $cppdefine_FILES $datestamp_FILES" - -# Assume all will go well. -RESULT=0 - -for BRANCH in $BRANCHES; do - echo "Working on \"$BRANCH\"." - # Check out the files on the branch. HEAD is a special case; if - # you check out files with -r HEAD, CVS will not let you check - # in changes. - if test "$BRANCH" = HEAD; then - ${CVS} co $FILES - else - ${CVS} co -r $BRANCH $FILES - fi - - # There are no files to commit yet. - COMMIT_FILES="" - - for file in $textstring_FILES; do - if test -f $file; then - /bin/sed <$file >$file.new -e \ - "s/\(.*\"[^ ]*\) [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/\1 ${CURR_DATE}/" - - if /usr/bin/cmp -s $file $file.new; then - rm -f $file.new - else - mv -f $file.new $file - COMMIT_FILES="$COMMIT_FILES $file" - fi - fi - done - - for file in $cppdefine_FILES; do - if test -f $file; then - /bin/sed <$file >$file.new -e \ - "s/\(#.*\) [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/\1 ${CURR_DATE}/" - - if /usr/bin/cmp -s $file $file.new; then - rm -f $file.new - else - mv -f $file.new $file - COMMIT_FILES="$COMMIT_FILES $file" - fi - fi - done - - for file in $datestamp_FILES; do - if test -f $file; then - echo ${CURR_DATE} > $file.new - - if /usr/bin/cmp -s $file $file.new; then - rm -f $file.new - else - mv -f $file.new $file - COMMIT_FILES="$COMMIT_FILES $file" - fi - fi - done - - if test -n "$COMMIT_FILES" \ - && ! ${CVS} commit -m "Daily bump." $COMMIT_FILES; then - # If we could not commit the files, indicate failure. - RESULT=1 - fi - - # Remove the files. - rm -rf gcc -done - -/bin/rm -rf /tmp/$$ -exit $RESULT diff --git a/maintainer-scripts/update_version_svn b/maintainer-scripts/update_version_svn index ba47687cd4f..1c87f1c50e9 100755 --- a/maintainer-scripts/update_version_svn +++ b/maintainer-scripts/update_version_svn @@ -6,7 +6,7 @@ # in $ADD_BRANCHES. SVNROOT=${SVNROOT:-"file:///svn/gcc"} -IGNORE_BRANCHES='gcc-(2_95|3_0|3_1|3_2|3_3|3_4|4_0)-branch' +IGNORE_BRANCHES='gcc-(2_95|3_0|3_1|3_2|3_3|3_4|4_0|4_1)-branch' ADD_BRANCHES='HEAD autovect-branch' # Run this from /tmp. @@ -29,17 +29,10 @@ BRANCHES="${BRANCHES} ${ADD_BRANCHES}" # ARGS is passed to 'cvs co' CURR_DATE=`/bin/date +"%Y%m%d"` -# version is contained within a char* -textstring_FILES="gcc/version.c" - -# version is contained within a #define -cppdefine_FILES="libstdc++-v3/include/bits/c++config" - # version is all there is datestamp_FILES="gcc/DATESTAMP" -FILES="$textstring_FILES $cppdefine_FILES $datestamp_FILES" -DIRS="$textstring_DIRS $cppdefine_DIRS $datestamp_DIRS" +FILES="$datestamp_FILES" # Assume all will go well. RESULT=0 @@ -60,40 +53,6 @@ for BRANCH in $BRANCHES; do # There are no files to commit yet. COMMIT_FILES="" - - for file in $textstring_FILES; do - dirname=`basename $file` - file=`basename $file` - file="$dirname/$file" - if test -f $file; then - /bin/sed <$file >$file.new -e \ - "s/\(.*\"[^ ]*\) [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/\1 ${CURR_DATE}/" - - if /usr/bin/cmp -s $file $file.new; then - rm -f $file.new - else - mv -f $file.new $file - COMMIT_FILES="$COMMIT_FILES $file" - fi - fi - done - - for file in $cppdefine_FILES; do - dirname=`basename $file` - file=`basename $file` - file="$dirname/$file" - if test -f $file; then - /bin/sed <$file >$file.new -e \ - "s/\(#.*\) [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/\1 ${CURR_DATE}/" - - if /usr/bin/cmp -s $file $file.new; then - rm -f $file.new - else - mv -f $file.new $file - COMMIT_FILES="$COMMIT_FILES $file" - fi - fi - done for file in $datestamp_FILES; do dirname=`basename $file` diff --git a/maintainer-scripts/update_web_docs_svn b/maintainer-scripts/update_web_docs_svn index 0fa9992b399..74098b4ac4d 100755 --- a/maintainer-scripts/update_web_docs_svn +++ b/maintainer-scripts/update_web_docs_svn @@ -17,7 +17,6 @@ MANUALS="cpp gcc gccint gcj - g77 gfortran gfc-internals gnat_ug_unx |