diff options
439 files changed, 13857 insertions, 5791 deletions
diff --git a/ChangeLog b/ChangeLog index 683541c15df..7e624711294 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-09-21 Iain Sandoe <iains@gcc.gnu.org> + + * configure.ac (enable-lto): Add Darwin to the list of supported lto + targets and amend comment. + * configure: Regenerate. + 2010-09-15 Tejas Belagod <tejas.belagod@arm.com> * MAINTAINERS (Write After Approval): Add myself. diff --git a/ChangeLog.MELT b/ChangeLog.MELT index 4cf71d75917..7b873f4d91e 100644 --- a/ChangeLog.MELT +++ b/ChangeLog.MELT @@ -1,4 +1,8 @@ +2010-09-27 Basile Starynkevitch <basile@starynkevitch.net> + + MELT branch merged with trunk rev 164647 + 2010-09-19 Basile Starynkevitch <basile@starynkevitch.net> MELT branch merged with trunk rev 164348, with some improvements in gcc/melt-runtime.[ch] diff --git a/configure b/configure index fc8f6b8da67..be41441b9be 100755 --- a/configure +++ b/configure @@ -6677,13 +6677,13 @@ else *) enable_lto=no ;; esac else - # Apart from ELF platforms, only Windows supports LTO so far. It - # would also be nice to check the binutils support, but we don't + # Apart from ELF platforms, only Windows and Darwin support LTO so far. + # It would also be nice to check the binutils support, but we don't # have gcc_GAS_CHECK_FEATURE available here. For now, we'll just # warn during gcc/ subconfigure; unless you're bootstrapping with # -flto it won't be needed until after installation anyway. case $target in - *-cygwin*|*-mingw*) ;; + *-cygwin*|*-mingw* | *-apple-darwin*) ;; *) if test x"$enable_lto" = x"yes"; then as_fn_error "LTO support is not enabled for this target." "$LINENO" 5 fi diff --git a/configure.ac b/configure.ac index 97a32467c3d..1346b89128e 100644 --- a/configure.ac +++ b/configure.ac @@ -1794,13 +1794,13 @@ fi],[if test x"$default_enable_lto" = x"yes" ; then *) enable_lto=no ;; esac else - # Apart from ELF platforms, only Windows supports LTO so far. It - # would also be nice to check the binutils support, but we don't + # Apart from ELF platforms, only Windows and Darwin support LTO so far. + # It would also be nice to check the binutils support, but we don't # have gcc_GAS_CHECK_FEATURE available here. For now, we'll just # warn during gcc/ subconfigure; unless you're bootstrapping with # -flto it won't be needed until after installation anyway. case $target in - *-cygwin*|*-mingw*) ;; + *-cygwin*|*-mingw* | *-apple-darwin*) ;; *) if test x"$enable_lto" = x"yes"; then AC_MSG_ERROR([LTO support is not enabled for this target.]) fi diff --git a/contrib/ChangeLog b/contrib/ChangeLog index 26c446c3be7..b98ef7bc989 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,15 @@ +2010-08-22 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * texi2pod.pl: Replace @@ before @{ and @}, for @samp{@@}. + Also escape characters with grave accents, to be fixed ... + (unmunge): ... here. + (postprocess): Also handle @/ and @acronym{...}. + +2010-07-02 Sebastian Pop <sebastian.pop@amd.com> + + * check_GNU_style.sh: Do not print warning messages when there are + no occurences. + 2010-09-13 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> * gcc_update: Handle hg, too. diff --git a/contrib/check_GNU_style.sh b/contrib/check_GNU_style.sh index 6396417fab7..8fb579fd160 100755 --- a/contrib/check_GNU_style.sh +++ b/contrib/check_GNU_style.sh @@ -84,8 +84,11 @@ col (){ | grep -v ':+++' \ | cut -f 2 -d '+' \ | awk '{ if (length ($0) > 80) print $0 }' \ - > $tmp && printf "\n$msg\n" - cat $tmp + > $tmp + if [ -s $tmp ]; then + printf "\n$msg\n" + cat $tmp + fi } col 'Lines should not exceed 80 characters.' $* diff --git a/contrib/texi2pod.pl b/contrib/texi2pod.pl index fcdc14550ba..5a4bbacdf5e 100755 --- a/contrib/texi2pod.pl +++ b/contrib/texi2pod.pl @@ -1,6 +1,6 @@ #! /usr/bin/perl -w -# Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. +# Copyright (C) 1999, 2000, 2001, 2003, 2010 Free Software Foundation, Inc. # This file is part of GCC. @@ -213,10 +213,12 @@ while(<$inf>) { # Now the ones that have to be replaced by special escapes # (which will be turned back into text by unmunge()) + # Replace @@ before @{ and @} in order to parse @samp{@@} correctly. s/&/&/g; + s/\@\@/&at;/g; s/\@\{/{/g; s/\@\}/}/g; - s/\@\@/&at;/g; + s/\@`\{(.)\}/&$1grave;/g; # Inside a verbatim block, handle @var, @samp and @url specially. if ($shift ne "") { @@ -391,9 +393,11 @@ sub postprocess s/\@(?:code|kbd)\{([^\}]*)\}/C<$1>/g; s/\@(?:samp|strong|key|option|env|command|b)\{([^\}]*)\}/B<$1>/g; s/\@sc\{([^\}]*)\}/\U$1/g; + s/\@acronym\{([^\}]*)\}/\U$1/g; s/\@file\{([^\}]*)\}/F<$1>/g; s/\@w\{([^\}]*)\}/S<$1>/g; s/\@(?:dmn|math)\{([^\}]*)\}/$1/g; + s/\@\///g; # keep references of the form @ref{...}, print them bold s/\@(?:ref)\{([^\}]*)\}/B<$1>/g; @@ -462,6 +466,7 @@ sub unmunge # Replace escaped symbols with their equivalents. local $_ = $_[0]; + s/&(.)grave;/E<$1grave>/g; s/</E<lt>/g; s/>/E<gt>/g; s/{/\{/g; diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 825abbf4bf2..58e8f2bb4c4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,947 @@ +2010-09-27 Jie Zhang <jie@codesourcery.com> + + * print-tree.c (print_node): Print in-constant-pool. + +2010-09-27 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.h (CLASS_MAX_NREGS): Also handle XCmode. + (UNITS_PER_WORD): Define only when IN_LIBGCC2 is undefined. + (MOVE_MAX_PIECES): Redefine using UNITS_PER_WORD. + (ASM_OUTPUT_AVX_PREFIX): Simplify pointer addition. + +2010-09-26 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.md (pro_epilogue_adjust_stack_<mode>_add): Merge + from pro_epilogue_adjust_stack_<mode>_{1,2}. + (pro_epilogue_adjust_stack_<mode>_add): Rename from + pro_epilogue_adjust_stack_<mode>_3. + * config/i386/i386.c (pro_epilogue_adjust_stack): Update for + renamed pro_epilogue_adjust_stack_{si,di}_add. + (ix86_expand_prologue): Use indirect functions. Update for renamed + pro_epilogue_adjust_stack_{si,di}_sub. + +2010-09-26 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.md (movmsk_df): New insn. + (signbitdf): Split out of signbit<mode>2. Generate movmsk_df + sequence for TARGET_SSE_MATH. + +2010-09-26 Richard Sandiford <rdsandiford@googlemail.com> + + * config/mips/mips.c (mips_builtin_decls): Declare. + (mips_init_builtins): Store function declarations in + mips_builtin_decls. + (mips_builtin_decl): New function. + (TARGET_BUILTIN_DECL): Define. + +2010-09-25 Kai Tietz <kai.tietz@onevision.com> + Richard Henderson <rth@redhat.com> + + * config/i386/cygwin.asm: Include auto-host.h. + (cfi_startproc, cfi_endproc, cfi_adjust_cfa_offset, + cfi_def_cfa_register, cfi_register, cfi_push, cfi_pop): New macros. + (__chkstk, __alloca): Annotate for dwarf2 unwind info. Drop + alignment code from the 64-bit path. Use gas local labels. + * config/i386/i386.md (pro_epilogue_adjust_stack_<mode>_2): Macroize + from _di_2. Remove the useless constant integer argument. + (pro_epilogue_adjust_stack_<mode>_3): New. + (allocate_stack_worker_probe_<mode>): Macroize from + allocate_stack_worker_{32,64}. Use __chkstk_ms. Update all users. + * config/i386/i386.c (ix86_expand_prologue): Use __chkstk_ms; + use gen_pro_epilogue_adjust_stack_*_3 and annotate it. + (__chkstk_ms): New function. + * config/i386/t-cygming (LIB1ASMFUNCS): Add _chkstk_ms. + * gcc/config/i386/t-interix: Likewise. + * configure.ac (HAVE_GAS_CFI_DIRECTIVE): Export for target. + (HAVE_GAS_CFI_PERSONALITY_DIRECTIVE): Likewise. + (HAVE_GAS_CFI_SECTIONS_DIRECTIVE): Likewise. + * configure, config.in: Rebuild. + +2010-09-25 Eric Botcazou <ebotcazou@adacore.com> + + * tree-inline.c (copy_bb): Use GSI_CONTINUE_LINKING when inserting new + statements because of the return slot optimization. + +2010-09-25 Anatoly Sokolov <aesok@post.ru> + + * config/avr/avr.h (CLASS_LIKELY_SPILLED_P): Remove. + * config/avr/avr-protos.h (class_likely_spilled_p): Remove. + * config/avr/avr.c (TARGET_CLASS_LIKELY_SPILLED_P): Define. + (class_likely_spilled_p): Rename to... + (avr_class_likely_spilled_p): ...this. Make static. Change argument + type to reg_class_t. + +2010-09-24 Jan Hubicka <jh@suse.cz> + + * lto-symtab.c (lto_symtab_entry_def): Add guessed field. + (lto_symtab_resolve_symbols): Set it. + (lto_symtab_merge_decls_1): Do not compute used_from_object_file; + store resolution field in cgraph/varpool. + * cgraph.c (cgraph_same_body_alias, cgraph_add_thunk): Return node. + (cgraph_get_node_or_alias, cgraph_get_node_or_alias): Constify. + (cgraph_dump_node): Drop used_from_object_file. + (cgraph_clone_node, cgraph_create_virtual_clone): Likewise. + (cgraph_function_body_availability): Use decl_replaceable_p. + (cgraph_make_node_local): Set resolution to LDPR_PREVAILING_DEF_IRONLY. + (cgraph_can_remove_if_no_direct_calls_and_refs): Use + cgraph_used_from_object_file_p. + (cgraph_will_be_removed_from_program_if_no_direct_calls): Use + cgraph_used_from_object_file_p. + (resolution_used_from_other_file_p): New functoin. + (cgraph_used_from_object_file_p): New predicate. + * cgraph.h: Include plugin-api.h + (struct cgraph_local_info): Remove used_from_object_file. + (struct cgraph_node): Add resolution field. + (struct varpool_node): Likewise; remove used_from_object_file; + reove const_value_known. + (cgraph_get_node, cgraph_get_node_or_alias, cgraph_node, + cgraph_same_body_alias, cgraph_add_thunk): Update prototypes. + (resolution_used_from_other_file_p, cgraph_used_from_object_file_p, + varpool_used_from_object_file_p): Declare. + (varpool_get_node, varpool_extra_name_alias): Update prototype. + * tree.h (DECL_REPLACEABLE_P): Remove. + (decl_replaceable_p, decl_binds_to_current_def_p): Declare. + * final.c (rest_of_clean_state): Use decl_binds_to_current_def_p. + * lto-cgraph.c (lto_output_node, lto_output_varpool_node, + input_overwrite_node, input_node, input_varpool_node): Stream + resolution. + * expr.c (expand_expr_real_1): Use const_value_known_p + * ipa.c (ipa_discover_readonly_nonaddressable_var): Do not set + const_value_known. + (cgraph_externally_visible_p): Use cgraph_used_from_object_file_p. + (function_and_variable_visibility): Set resolution for local vars + and functions; use varpool_used_from_object_file_p. + * varasm.c (resolution_to_local_definition_p, resolution_local_p): New + static functions. + (default_binds_local_p_1): Use resolutoin info. + (decl_binds_to_current_def_p, decl_replaceable_p): New functions. + * varpool.c (varpool_get_node): Constify. + (const_value_known_p): Do not use vnode->const_value_known; + use decl_replaceable_p. + (varpool_finalize_decl): Do not set const_value_known. + (cgraph_variable_initializer_availability): Use decl_replaceable_p + (varpool_extra_name_alias): Return new node. + (varpool_used_from_object_file_p): New function. + +2010-09-24 Richard Henderson <rth@redhat.com> + + * config/ia64/ia64.c (ia64_dwarf_handle_frame_unspec): New. + (TARGET_DWARF_HANDLE_FRAME_UNSPEC): New. + (do_spill): Use REG_CFA_OFFSET. + (ia64_expand_prologue): Use REG_CFA_ADJUST_CFA and REG_CFA_REGISTER + as appropriate. + (ia64_expand_epilogue): Likewise. + (process_set): Split into ... + (process_cfa_adjust_cfa): this, + (process_cfa_register): this, + (process_cfa_offset): and this new function. + (ia64_asm_unwind_emit): Use them. Expect REG_CFA_* notes + instead of REG_FRAME_RELATED_EXPR. + +2010-09-24 Olivier Hainque <hainque@adacore.com> + + * config/i386/vx-common.h (DBX_REGISTER_NUMBER): Reinstate. + +2010-09-24 Jan Hubicka <jh@suse.cz> + + * doc/extend.texi: (attribute leaf): Document. + * tree.c (local_define_builtin): Handle ECF_LEAF. + (build_common_builtin_nodes): Set ECF_LEAF where needed. + * tree.h (ECF_LEAF): New. + * ipa-reference.c (propagate_bits): For leaf calls propagate ever + overwrittable and unavailable functions. + (ipa_init): Put all_module_statics into optimization_summary_obstack. + (copy_global_bitmap): Do not copy all_module_statics. + (read_write_all_from_decl): Use cgraph_node argument; handle ECF_LEAF. + (propagate): Handle overwritable and unavailable leaf functions; + initialize global info for overwritable and unavailable leaf functions; + do not free all module statics. + (ipa_reference_get_not_read_global, + ipa_reference_get_not_written_global): leaf calls don't clobber + local statics. + * calls.c (flags_from_decl_or_type): Handle leaf. + * tree-cfg.c (stmt_can_make_abnormal_goto): Leaf functions can't do + abnormal gotos. + +2010-09-24 Basile Starynkevitch <basile@starynkevitch.net> + + * gengtype.c: Reindented. + * gengtype.h: Reindented. + * gengtype-parse.c: Reindented. + +2010-09-24 Jan Hubicka <jh@suse.cz> + + PR tree-optimization/45738 + PR tree-optimization/45741 + * expr.c (string_constant): Allow CONST_DECL too; + check that DECL_INITIAL is set. + * varpool.c (const_value_known_p): Only look into VAR_DECL + and CONST_DECL. + +2010-09-24 Joseph Myers <joseph@codesourcery.com> + + * common.opt (undef): New. + +2010-09-24 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/45234 + * rtl.h (enum global_rtl_index): Add + GR_VIRTUAL_PREFERRED_STACK_BOUNDARY. + (LAST_VIRTUAL_POINTER_REGISTER): Define. + (virtual_preferred_stack_boundary_rtx, + VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM): Define. + (LAST_VIRTUAL_REGISTER): Increase by one. + (REGNO_PTR_FRAME_P): Use LAST_VIRTUAL_POINTER_REGISTER + instead of LAST_VIRTUAL_REGISTER. + * function.c (instantiate_new_reg): Handle + virtual_preferred_stack_boundary_rtx. + * emit-rtl.c (init_virtual_regs): Handle + VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM. + (init_emit_regs): Initialize virtual_preferred_stack_boundary_rtx. + * explow.c (round_push): If crtl->preferred_stack_boundary + is smaller than MAX_SUPPORTED_STACK_ALIGNMENT, use + virtual_preferred_stack_boundary_rtx alignment instead of + crtl->preferred_stack_boundary alignment. + (allocate_dynamic_stack_space): Use CONST_INT_P and REG_P + macros. Never decrease crtl->preferred_stack_boundary, + use crtl->preferred_stack_boundary or MAX_SUPPORTED_STACK_ALIGNMENT + instead of PREFERRED_STACK_BOUNDARY. Don't modify + stack_pointer_delta in dynamic allocation, even when size + is constant. + (probe_stack_range, anti_adjust_stack_and_probe): Use CONST_INT_P + macro. + * print-rtl.c (print_rtx): Handle + VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM. + * config/alpha/alpha.h (NONSTRICT_REG_OK_FP_BASE_P): Use + LAST_VIRTUAL_POINTER_REGISTER instead of LAST_VIRTUAL_REGISTER. + * config/frv/frv.c (frv_emit_movsi): Likewise. + * config/arm/arm.c (thumb1_legitimate_address_p): Likewise. + * config/rs6000/rs6000.c (virtual_stack_registers_memory_p): + Likewise. + + Revert: + 2010-09-17 H.J. Lu <hongjiu.lu@intel.com> + + PR middle-end/45234 + * calls.c (expand_call): Make sure that all variable sized + adjustments are multiple of preferred stack boundary after + stack alignment. + +2010-09-24 Iain Sandoe <iains@gcc.gnu.org> + Dominique Dhumieres <dominiq@lps.ens.fr> + + PR bootstrap/45751 + * gcc/config/darwin-driver.c (darwin_default_min_version): + Adjust size passed to memcpy in two places. + +2010-09-24 Richard Guenther <rguenther@suse.de> + + * c-decl.c (pop_scope): Always set file-scope DECL_CONTEXT. + Make sure to not call set_type_context with error_mark_node. + * langhooks.c (lhd_set_decl_assembler_name): Use DECL_FILE_SCOPE_P. + +2010-09-24 Richard Guenther <rguenther@suse.de> + + * Makefile.in (OBJS-onestep): Remove. + (ALL_HOST_BACKEND_OBJS): Remove libbackend.o. + (libbackend.a): Remove onestep support. + (libbackend.o): Remove. + * configure.ac (--enable-intermodule): Remove. + * configure: Regenerate. + +2010-09-24 Bernd Schmidt <bernds@codesourcery.com> + + * cfgcleanup.c (flow_find_head_matching_sequence): Terminate when + reaching the end of a block if it occurs at a DEBUG_INSN. + +2010-09-09 Tristan Gingold <gingold@adacore.com> + + PR target/44242 + * config/vms/vms-crt0-64.c: Removed. + * config/vms/vms-crt0.c: Removed. + * config/vms/vms-psxcrt0-64.c: Removed. + * config/vms/vms-psxcrt0.c: Removed. + * config/vms/vms-ucrt0.c: New file. + * config/vms/t-vms64: Removed. + * config/vms/t-vms (VMS_EXTRA_PARTS): Uncomment it. Remove DECC. + Use $(GCC_FOR_TARGET) to build pcrt0.o and vcrt0.o + * config.gcc (alpha-dec-vms): Use t-vms. + +2010-09-24 Nicola Pero <nicola.pero@meta-innovation.com> + + * doc/invoke.texi (-fno-nil-receivers): Tidied up line to remove + underfull hbox in DVI output. + (-fobjc-class-cxx-cdtors): Same change. + (-fobjc-exceptions): Tidied up documentation. Explain what the + option does, but moved the (lenghty) description of the exception + syntax into objc.texi. + (-fobjc-gc): Explain that the option is not useful with the GNU + runtime. + (-fzero-link): Explain that the GNU runtime always works in + "zero-link" mode. + * doc/objc.texi: All sections: simplified @node declarations + removing specification of next, previous, up node. + (Objective-C): Updated introduction. + (Garbage Collection): Updated. The bohem-gc library is now + included in gcc itself. Mention that this section only applies to + the GNU Objective-C runtime. + (compatibility_alias): Small tidy up. + (Exceptions): New section mostly containing text previously in the + description of the -fobjc-exception command-line option. + (Synchronization): Same. + +2010-09-24 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.md (ix86_code_end): Move the initialization of + xops array near the consumer. Use AX_REG and SP_REG instead of + numerical constants. + +2010-09-24 Nicola Pero <nicola.pero@meta-innovation.com> + + * c-typeck.c (convert_arguments): Use warning 'too many arguments to + method [methodname]' for an Objective-C method instead of the less + satisfactory 'too many arguments to function' (with no method name). + +2010-09-23 Eric Botcazou <ebotcazou@adacore.com> + + * tree-flow.h (execute_update_addresses_taken): Remove parameter. + * tree-ssa.c (maybe_optimize_var): Tweak comment and dump messages. + (execute_update_addresses_taken): Remove parameter. Execute the + optimization unconditionally. + * passes.c (execute_function_todo): Call execute_update_addresses_taken + unconditionally if TODO_rebuild_alias is set, else only when optimizing + if TODO_update_address_taken is set. + +2010-09-23 Anatoly Sokolov <aesok@post.ru> + + * config/arm/arm.h (OUTPUT_ADDR_CONST_EXTRA): Remove. + * config/arm/arm-protos.h (arm_output_addr_const_extra): Remove. + * config/arm/arm.c (TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA): Define. + (arm_output_addr_const_extra): Make static. + +2010-09-23 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.md (UNSPECV_NOPS): Rename from UNSPEC_NOPS and + define as unspec_volatile. + ("nops"): Define as unspec_volatile. Use fputs to write to + asm_out_file directly. Output NOPs on separate lines using while loop. + * config/i386/i386.c (ix86_code_end): Use fputs to write to + asm_out_file directly. Output NOPs on separate lines using while loop. + +2010-09-23 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45565 + * cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): + Make sure to adjust the fndecl before replacing the stmt. + +2010-09-23 Richard Guenther <rguenther@suse.de> + + PR middle-end/45750 + * gimplify.c (gimplify_expr): Properly pass on GS_ERROR when + gimplifying MEM_REF. + +2010-09-23 Alan Modra <amodra@gmail.com> + + * config/rs6000/rs6000.c (toc_relative_ok): Delete. + (rs6000_emit_move): Use SYMBOL_REF_LOCAL_P instead. + +2010-09-23 Bernd Schmidt <bernds@codesourcery.com> + + PR rtl-optimization/44374 + * basic-block.h (enum bb_flags): Add BB_MODIFIED. + * df-core.c (df_set_bb_dirty): Set it. + * ifcvt.c (find_memory): Remove function. + (dead_or_predicable): Use can_move_insns_across. + * df.h (can_move_insns_across): Declare function. + * cfgcleanup.c (block_was_dirty): New static variable. + (try_crossjump_bb, try_forward_edges): Test BB_MODIFIED flag rather + than df_get_bb_dirty. + (try_head_merge_bb): New static function. + (try_optimize_cfg): Call it. Call df_analyze if block_was_dirty + is set. + * df-problems.c: Include "target.h" + (df_simulate_find_uses): New static function. + (MEMREF_NORMAL, MEMREF_VOLATILE): New macros. + (find_memory, find_memory_store): New static functions. + (can_move_insns_across): New function. + * Makefile.in (df-problems.o): Update dependencies. + +2010-09-22 Eric Botcazou <ebotcazou@adacore.com> + + PR java/44095 + * config/sparc/linux.h (ASM_SPEC): Pass -K PIC if -findirect-dispatch + is specified and the suffix of the file isn't ".c". + * config/sparc/linux64.h (ASM_SPEC): Likewise. + +2010-09-22 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * doc/contrib.texi (Contributors): Allow URL to wrap in PDF output. + * doc/cppopts.texi: Fix markup of index entry. + * doc/extend.texi (Constructing Calls): Fix markup of + __builtin_va_arg_pack and __builtin_va_arg_pack_len definition. + (Conditionals, C++ Comments, Pragmas, Unnamed Fields, Thread-Local) + (Vague Linkage, C++ Attributes): Fix markup of index entries and + keywords. + * doc/invoke.texi (Option Summary): Fix spacing. Rewrap to + avoid long lines. + (C Dialect Options, C++ Dialect Options, Warning Options) + (Debugging Options, Spec Files, Darwin Options) + (i386 and x86-64 Options, MIPS Options) + (RS/6000 and PowerPC Options, Code Gen Options): Fix markup of + index entries, avoid abbreviations, allow URLs to wrap, avoid + long lines, avoid overlong pages from long @itemx lists. + * doc/objc.texi (Garbage Collection): Allow URLs to wrap. + * doc/standards.texi (Standards): Likewise. + * doc/trouble.texi (Incompatibilities): Fix markup of index entry. + +2010-09-22 Joseph Myers <joseph@codesourcery.com> + + * opts-common.c (prune_options): Make static. Work with decoded + options. + (decode_cmdline_options_to_array): Call prune_options. Don't + resize option array here. + * opts.h (prune_options): Remove prototype. + * gcc.c (process_command): Take decoded options; don't call + decode_cmdline_options_to_array here. Use decoded options for argv[0]. + (main): Call decode_cmdline_options_to_array here instead of + prune_options. Update call to process_command. + * config/darwin-driver.c: Include opts.h. + (darwin_default_min_version): Work with decoded options. Don't + handle -b or -V here. + * config/darwin.h (darwin_default_min_version): Update prototype. + (GCC_DRIVER_HOST_INITIALIZATION): Update call to + darwin_default_min_version. + * config/i386/cygwin.h (mingw_scan): Update prototype. + (GCC_DRIVER_HOST_INITIALIZATION): Update call to mingw_scan. + * config/i386/cygwin1.c: Include opts.h. + (mingw_scan): Work with decoded options. + * config/i386/t-cygwin (cygwin1.o): Update dependencies. + * config/t-darwin (darwin-driver.o): Update dependencies. + +2010-09-22 Joseph Myers <joseph@codesourcery.com> + + * common.opt (-assemble, -compile, -coverage, -debug, -dump, + -dump=, -dumpbase, -dumpdir, -entry, -entry=, -extra-warnings, + -for-assembler, -for-assembler=, -for-linker, -for-linker=, + -force-link, -force-link=, -language, -language=, + -library-directory, -library-directory=, -no-canonical-prefixes, + -no-standard-libraries, -no-warnings, -optimize, -output, + -output=, -pass-exit-codes, -pedantic, -pedantic-errors, -pie, + -pipe, -prefix, -prefix=, -preprocess, -print-file-name, + -print-file-name=, -print-libgcc-file-name, + -print-multi-directory, -print-multi-lib, + -print-multi-os-directory, -print-prog-name, -print-prog-name=, + -print-search-dirs, -print-sysroot, -print-sysroot-headers-suffix, + -profile, -save-temps, -shared, -specs, -specs=, -static, + -symbolic, -time, -verbose, -param=, -sysroot, coverage, e, u, + symbolic): New. + (fhelp, fhelp=, ftarget-help, fversion): Make into aliases. + * gcc.c (A Short Introduction to Adding a Command-Line Option): + Remove comment. + (cc1_options): Correct specs for passing down --help, + --target-help and --help=*. Add spec for passing down --version. + (struct option_map, option_map, target_option_translations, + translate_options): Remove. + (driver_handle_option): Handle OPT__version, OPT__help, OPT__help_ + and OPT__target_help instead of OPT_fversion, OPT_fhelp, + OPT_fhelp_ and OPT_ftarget_help. + (process_command): Don't call translate_options. Call + decode_cmdline_options_to_array before checking for + -no-canonical-prefixes using decoded options. + * opts-common.c (tm.h): Update comment on #include. + (find_opt): Allow abbreviations of long options. + (struct option_map, option_map): New. + (decode_cmdline_option): Use them instead of hardcoding -Wno, -fno + and -mno handling. + (target_option_translations): New. + (decode_cmdline_options_to_array): Handle + TARGET_OPTION_TRANSLATE_TABLE in driver. + * opts.c (common_handle_option): Don't handle OPT_fhelp, + OPT_ftarget_help, OPT_fhelp_ or OPT_fversion. + +2010-09-22 Richard Guenther <rguenther@suse.de> + + * tree-inline.c (optimize_inline_calls): Schedule cleanups + only if we inlined something. Block compaction and conditional + folding are done by cfg cleanup. Schedule update-address-taken. + (tree_function_versioning): Remove redundant call to number_blocks. + * tree-optimize.c (execute_cleanup_cfg_post_optimizing): Conditional + folding is done by cfg cleanup. + * passes.c (init_optimization_passes): Remove update-address-taken + pass after IPA inlining. + +2010-09-22 Chung-Lin Tang <cltang@codesourcery.com> + + * postreload.c (move2add_note_store): Add reg_symbol_ref[] checks + to update conditions. Fix reg_mode[] check. + +2010-09-22 Hariharan Sandanagobalane <hariharan@picochip.com> + + * config/picochip/picochip.md (movhicc): Use expand to check whether + movhicc is available and split it after reload. + +2010-09-22 Richard Guenther <rguenther@suse.de> + + * tree-ssanames.c (release_dead_ssa_names): Do not remove + callee edges here. + * passes.c (init_optimization_passes): Remove early CFG cleanup. + * tree-optimize.c (execute_cleanup_cfg_pre_ipa): Remove. + (pass_cleanup_cfg): Likewise. + (execute_fixup_cfg): Cleanup. + * tree-pass.h (pass_cleanup_cfg): Remove. + +2010-09-22 Martin Jambor <mjambor@suse.cz> + + * gimple-fold.c (fold_gimple_call): New parameter inplace, do not fold + builtins if it is true. + (fold_stmt_1): Call, fold_gimple_call always, pass inplace as a + parameter. + +2010-09-22 Martin Jambor <mjambor@suse.cz> + + * tree-sra.c (struct access): New field grp_no_warning. + (create_access_replacement): Set TREE_NO_WARNING according to + grp_no_warning. + (create_artificial_child_access): Use build_ref_for_model and set + grp_no_warning if build_user_friendly_ref_for_offset fails. + (propagate_subaccesses_across_link): Likewise. + +2010-09-22 Eric Botcazou <ebotcazou@adacore.com> + + PR target/35664 + * config/sparc/constraints.md ('e'): Return NO_REGS if !TARGET_FPU. + ('f'): Likewise. + +2010-09-22 Tristan Gingold <gingold@adacore.com> + + * config/alpha/alpha.c (alpha_use_linkage): Initialize target field. + +2010-09-22 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.h (MAX_STRINGOP_ALGS): Fix typo in the name. + * config/i386/i386.c (decide_alg): Update for rename. + +2010-09-22 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/45739 + * simplify-rtx.c (simplify_binary_operation_1): Optimize even + vector mode | CONST0_RTX (mode) and ^ CONST0_RTX (mode). + +2010-09-21 Anatoly Sokolov <aesok@post.ru> + + * config/rs6000/rs6000.h (OUTPUT_ADDR_CONST_EXTRA): Remove macros. + * config/rs6000/rs6000-protos.h (rs6000_output_addr_const_extra): + Remove. + * config/rs6000/rs6000.c (rs6000_output_addr_const_extra): Make static. + (TTARGET_ASM_OUTPUT_ADDR_CONST_EXTRA): Define. + +2010-09-21 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/23710 + * c-parser.c (c_parser_objc_method_definition): Check the return + value of objc_start_method_definition and if false is returned, + parse the method definition but emit no code. + +2010-09-21 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/25965 + * c-decl.c (detect_field_duplicates): If compiling Objective-C, + call objc_get_interface_ivars (). + +2010-09-21 Kai Tietz <kai.tietz@onevision.com> + + PR target/45694 + * config/i386/i386.c (ix86_expand_prologue): Save r10 in case that + static chain-register is used for 64-bit. + +2010-09-21 Richard Guenther <rguenther@suse.de> + + * dwarf2out.c (is_cu_die): New function. + (add_pubtype): Use it. + (gen_subprogram_die): Likewise. + (gen_struct_or_union_type_die): Likewise. + (dwarf2out_finish): Likewise. + (comp_unit_die): Rename to ... + (single_comp_unit_die): ... this. + (comp_unit_die): New function lazily constructing and + returning single_comp_unit_die. + (is_cxx, is_fortran, is_ada, debug_dwarf, break_out_comdat_types, + base_type_die, subrange_type_die, modified_type_die, + lower_bound_default, add_bound_info, add_prototyped_attribute, + dwarf2out_vms_debug_main_pointer, scope_die_for, retry_incomplete_types, + dwarf2out_abstract_function, gen_type_die_with_usage, get_context_die, + force_decl_die, gen_namespace_die, dwarf2out_decl, + dwarf2out_start_source_file, dwarf2out_end_source_file, + prune_unused_types, dwarf2out_finish): Use it. + (gen_compile_unit_die): For GNU GIMPLE derive DW_AT_language from + the global list of translation-unit decls. + (dwarf2out_init): Do not create single_comp_unit_die here. + (force_decl_die): Handle TRANSLATION_UNIT_DECL. + +2010-09-21 Richard Guenther <rguenther@suse.de> + + * dwarf2out.c (dwarf2out_decl): Do not always generate a DIE + for bool for C++. + +2010-09-21 Bernd Schmidt <bernds@codesourcery.com> + + * config/arm/iterators.md (qhs_extenddi_op): New mode_attr. + (qhs_extenddi_cstr): Likewise. + * config/arm/arm.md (zero_extend<mode>di2, extend<mode>di2): Use + them for the source operand. + +2010-09-21 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.c (ix86_split_ashl): Rename single_width variable + to half_width. Use GET_MODE_BITSIZE to calculate mode size. + (ix86_split_ashr): Ditto. + (ix86_split_lshr): Ditto. + +2010-09-21 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45580 + * tree-ssa-propagate.c (substitute_and_fold): Always replace + regular uses. + * gimple-fold.c (gimple_fold_obj_type_ref): For a BINFO without + virtuals fold the call into a regular indirect one. + +2010-09-20 Eric Botcazou <ebotcazou@adacore.com> + + PR rtl-optimization/42775 + * cfgrtl.c (rest_of_pass_free_cfg): Recompute notes if delay slot + scheduling is enabled. + +2010-09-20 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/45728 + * expr.c (expand_expr_real_1): If op0 isn't REG or MEM, try + gen_lowpart_common first and if that fails, force_reg first + before calling gen_lowpart. + + PR middle-end/45678 + * cfgexpand.c (expand_one_stack_var_at): Use + crtl->max_used_stack_slot_alignment as max_align, instead + of maximum of that and PREFERRED_STACK_BOUNDARY. + Don't call update_stack_alignment. + +2010-09-20 Eric Botcazou <ebotcazou@adacore.com> + + * langhooks.h (struct lang_hooks_for_types): Remove hash_types field. + * langhooks-def.h (LANG_HOOKS_HASH_TYPES): Delete. + (LANG_HOOKS_FOR_TYPES_INITIALIZER): Remove LANG_HOOKS_HASH_TYPES. + * system.h (LANG_HOOKS_HASH_TYPES): Poison. + * tree.c (type_hash_canon): Do not test lang_hooks.types.hash_types. + (build_nonstandard_integer_type): Likewise. + (build_range_type_1): New function, built from... + (build_range_type): ...this. Call build_range_type_1. + (build_nonshared_range_type): New function. + (build_array_type_1): New function, built from... + (build_array_type: ...this. Call build_array_type_1. + (build_nonshared_array_type): New function. + * tree.h (build_nonshared_range_type): Declare. + (build_nonshared_array_type): Likewise. + +2010-09-20 Anatoly Sokolov <aesok@post.ru> + + * config/arm/arm.h (CLASS_LIKELY_SPILLED_P): Remove. + * config/arm/arm.c (TARGET_CLASS_LIKELY_SPILLED_P): Define. + (arm_class_likely_spilled_p): New function. + +2010-09-20 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.c (ix86_expand_ashl_const): Rewrite using + indirect functions. + (ix86_split_ashl): Ditto. + (ix86_split_ashr): Ditto. + (ix86_split_lshr): Ditto. + (ix86_adjust_counter): Ditto. + +2010-09-20 Nicola Pero <nicola.pero@meta-innovation.com> + + * c-family/c-common.h (constant_string_class): Documented with + comment identical to the one already in c-common.c. + +2010-09-20 Jakub Jelinek <jakub@redhat.com> + + * dwarf2out.c (any_cfis_emitted): New static variable. + (add_fde_cfi): Set it. + (dwarf2out_frame_debug): Clear it before processing, + if it is set afterwards, flush any queued reg saves. + + PR debug/45124 + * dwarf2out.c (add_accessibility_attribute): Assume + DW_ACCESS_private as the default for dwarf_version > 2 + and DW_TAG_class_type parent. + (gen_inheritance_die): Assume DW_ACCESS_public as the default + for dwarf_version > 2 and parent other than DW_TAG_class_type. + +2010-09-20 Rafael Carre <rafael.carre@gmail.com> + + PR target/45726 + * arm.md (arm_movt): Only enable on machines with MOVT. + +2010-09-20 Jie Zhang <jie@codesourcery.com> + + * config/arm/arm.c (arm_address_offset_is_imm): New. + (arm_early_store_addr_dep): New. + (arm_early_load_addr_dep): New. + * config/arm/arm-protos.h (arm_early_store_addr_dep): Declare. + (arm_early_load_addr_dep): Declare. + (arm_address_offset_is_imm): Declare. + * config/arm/cortex-m4.md: New file. + * config/arm/cortex-m4-fpu.md: New file. + * config/arm/arm.md: Include cortex-m4.md and cortex-m4-fpu.md. + (attr generic_sched): Exclude cortexm4. + (attr generic_vfp): Exclude cortexm4. + +2010-09-20 Richard Guenther <rguenther@suse.de> + + PR middle-end/45704 + * gimplify.c (gimplify_modify_expr_rhs): Preserve volatileness. + +2010-09-20 Jan Hubicka <jh@suse.cz> + + PR tree-optimize/45605 + * cgraph.h (const_value_known_p): Declare. + (varpool_decide_const_value_known): Remove. + * tree-ssa-ccp.c (get_base_constructor): Use it. + * lto-cgraph.c (compute_ltrans_boundary): Likewise. + * expr.c (string_constant): Likewise. + * tree-ssa-loop-ivcanon.c (constant_after_peeling): Likewise. + * ipa.c (ipa_discover_readonly_nonaddressable_var, + function_and_variable_visibility): Likewise. + * gimplify.c (gimplify_call_expr): Likewise. + * gimple-fold.c (get_symbol_constant_value): Likewise. + * varpool.c (varpool_decide_const_value_known): Replace by... + (const_value_known_p): ... this one; handle other kinds of DECLs + too and work for automatic vars. + (varpool_finalize_decl): Use const_value_known_p. + +2010-09-20 Rafael Carre <rafael.carre@gmail.com> + + PR target/45726 + * arm.md (arm_movtas_ze): Only enable on machine with MOVT. + +2010-09-20 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45705 + * tree-ssa-dom.c (optimize_stmt): Perform redundant store elimination. + +2010-09-20 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/45695 + * combine.c (try_combine): When splitting a two set pattern, + make sure the pattern which will be put into i2 doesn't use REGs + or MEMs set by insns in between i2 and i3. + +2010-09-19 Jan Hubicka <jh@suse.cz> + + PR lto/44246 + * lto-cgraph.c (input_cgraph_1, input_varpool_1): Avoid + processing same node twice. + +2010-09-19 Anatoly Sokolov <aesok@post.ru> + + * config/bfin/bfin.h (CLASS_LIKELY_SPILLED_P): Remove. + * config/bfin/bfin.c (TARGET_CLASS_LIKELY_SPILLED_P): Define. + (bfin_class_likely_spilled_p): New function + +2010-09-19 Ira Rosen <irar@il.ibm.com> + + PR tree-optimization/45714 + * tree-vect-stmts.c (vect_transform_stmt): Use a dummy statement + created in vectorizable_call instead of the original statement in + def stmt updates. + +2010-09-19 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386-protos.h (split_double_mode): New prototype. + (split_di, split_ti): Remove prototypes. + * config/i386/i386.c (split_double_mode): New function. + (split_di, split_ti): Remove. + (ix86_expand_branch): Use split_double_mode. + (ix86_split_to_parts): Ditto. + (ix86_split_ashl): Ditto. + (ix86_split_ashr): Ditto. + (ix86_split_lshr): Ditto. + (ix86_force_to_memory): Ditto. + * config/i386/i386.md: Use split_double_mode in double-mode splitters. + +2010-09-18 Jan Hubicka <jh@suse.cz> + + PR tree-optimization/45453 + * cgraphunit.c (cgraph_finalize_function): Consider comdat & external + virtual functions are reachable. + * ipa-inline.c (cgraph_clone_inlined_nodes): Likewise. + * ipa.c (cgraph_remove_unreachable_nodes): Likewise. + * ipa-prop.c (ipa_modify_formal_parameters): Clear DECL_VIRTUAL_P + when modifying function. + +2010-09-18 Jan Hubicka <jh@suse.cz> + + PR tree-optimization/45605 + * cgraphunit.c (cgraph_analyze_functions): Allocate bitmap obstack. + * gimple-fold.c (static_object_in_other_unit_p): New function. + (canonicalize_constructor_val): Use it. + (get_symbol_constant_value): Be reaqdy for canonicalize_constructor_val + returning NULL. + (gimple_fold_obj_type_ref_known_binfo): Use + static_object_in_other_unit_p. + +2010-09-18 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45709 + * tree-inline.c (copy_phis_for_bb): Delay commit of edge + insertions until after all PHI nodes of the block are processed. + +2010-09-18 Tijl Coosemans <tijl@coosemans.org> + + * config/i386/freebsd.h (SUBTARGET32_DEFAULT_CPU): Add. + +2010-09-18 Kai Tietz <kai.tietz@onevision.com> + + * config.gcc (*-w64-mingw*): Correct typo about t-dfprules. + +2010-09-18 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45709 + * tree-inline.c (copy_phis_for_bb): Fixup new_edge when we splitted it. + +2010-09-17 Sebastian Pop <sebastian.pop@amd.com> + + * graphite-dependences.c (dot_deps): Add DEBUG_FUNCTION. + (dot_deps_stmt): Same. + * graphite-poly.c (dot_lst): Same. + * graphite-scop-detection.c (dot_all_scops): Same. + (dot_scop): Same. + +2010-09-17 Sebastian Pop <sebastian.pop@amd.com> + + Revert: + 2009-12-16 Ben Elliston <bje@au.ibm.com> + + * tree-data-ref.c (dot_rdg_1): Added back. + (dot_rdg): Same. Added "#if 0" around system call. + +2010-09-17 H.J. Lu <hongjiu.lu@intel.com> + Richard Henderson <rth@redhat.com> + + * config/i386/i386.c (initial_ix86_tune_features): Add + X86_TUNE_PAD_SHORT_FUNCTION. + (ix86_code_end): Pad with 8 NOPs for TARGET_PAD_SHORT_FUNCTION. + (ix86_count_insn): New. + (ix86_pad_short_function): Likewise. + (ix86_reorg): Support TARGET_PAD_SHORT_FUNCTION. + + * config/i386/i386.h (ix86_tune_indices): Add + X86_TUNE_PAD_SHORT_FUNCTION. + (TARGET_PAD_SHORT_FUNCTION): New. + + * config/i386/i386.md (UNSPEC_NOPS): New. + (nops): Likewise. + +2010-09-17 H.J. Lu <hongjiu.lu@intel.com> + + PR middle-end/45234 + * calls.c (expand_call): Make sure that all variable sized + adjustments are multiple of preferred stack boundary after + stack alignment. + +2010-09-17 DJ Delorie <dj@redhat.com> + + * config/rx/rx.c (rx_print_operand): If __builtin_rx_setpsw() is + passed an invalid value, print an error instead of ICEing. + (valid_psw_flag): New. + (rx_expand_builtin): Call it for setpsw/clrpsw. + (rx_expand_builtin_mvtipl): Pass an integer to IN_RANGE, not an RTX. + + * config/rx/rx.md (bitclr): Don't mark the output as early-clobber. + (bitclr_in_memory): Likewise. + (clrspw, setpsw, mvfc, mvtc, mvtipl): Make volatile. + +2010-09-17 H.J. Lu <hongjiu.lu@intel.com> + + PR middle-end/45678 + * cfgexpand.c (update_stack_alignment): New. + (get_decl_align_unit): Use it. + (expand_one_stack_var_at): Call update_stack_alignment. + +2010-09-17 Richard Guenther <rguenther@suse.de> + + * lto-streamer-in.c (lto_input_ts_translation_unit_decl_tree_pointers): + Properly copy the read string. + +2010-09-17 Joseph Myers <joseph@codesourcery.com> + + * doc/options.texi (Variable): Document. + * optc-gen.awk, opth-gen.awk: Handle Variable records. Don't + generate target_flags declarations explicitly. Don't define + VarExists variables for the driver. + * common.opt (target_flags): New Variable record. + (flag_dump_unnumbered, flag_dump_unnumbered_links, + flag_var_tracking, flag_var_tracking_assignments, + flag_var_tracking_assignments_toggle): Don't mark variables with + VarExists. + * config/i386/i386.c (ix86_isa_flags): Don't define here. + * config/i386/i386.opt (ix86_isa_flags): Define here. + * config/mcore/mcore.c (mcore_stack_increment): Don't define here. + * config/mcore/mcore.opt (mcore_stack_increment): Don't mark with + VarExists. + * flags.h (flag_dump_unnumbered, flag_var_tracking): Remove. + * print-rtl.c (flag_dump_unnumbered, flag_dump_unnumbered_links): + Only define for generator programs. + * rtlanal.c (target_flags): Remove. + * toplev.c (flag_var_tracking, flag_var_tracking_assignments, + flag_var_tracking_assignments_toggle): Remove. + +2010-09-17 Michael Matz <matz@suse.de> + + PR tree-optimization/43432 + * tree-vect-data-refs.c (vect_analyze_data_ref_access): + Accept backwards consecutive accesses. + (vect_create_data_ref_ptr): If step is negative generate + decreasing IVs. + * tree-vect-stmts.c (vectorizable_store): Reject negative steps. + (perm_mask_for_reverse, reverse_vec_elements): New functions. + (vectorizable_load): Handle loads with negative steps when easily + possible. + +2010-09-03 Jan Hubicka <jh@suse.cz> + + * lto-cgraph.c (compute_ltrans_boundary): Use const_value_known. + +2010-09-03 Naveen H.S <naveen.S@kpitcummins.com> + + * config/v850/v850.c (v850_function_value_regno_p): Make static. + Adjust comments. Declare. + (TARGET_FUNCTION_VALUE_REGNO_P): Define. + * config/v850/v850.h (FUNCTION_VALUE_REGNO_P): Delete. + +2010-09-17 Richard Guenther <rguenther@suse.de> + + * common.opt (combine): Remove. + * gcc.c (default_compilers): Remove specs testing combine. + The C compilers no longer can combine. + (option_map): Remove -combine. + (display_help): Remove -combine. + (driver_handle_option): Remove OPT_combine handling. + (compile_input_file_p): Remove. + (do_spec): Remove code concerning combine. + (main): Likewise. + * doc/invoke.texi: Remove traces of -combine. + * lto-wrapper.c (run_gcc): Do not pass -combine to the compiler driver. + +2010-09-17 Richard Guenther <rguenther@suse.de> + + PR middle-end/45678 + * builtins.c (fold_builtin_memory_op): Always properly adjust + alignment of memory accesses. + +2010-09-16 Jan Hubicka <jh@suse.cz> + + * lto-cgraph.c (input_overwrite_node): Do not set DECL_EXTERNAL when + processing clone. + 2010-09-16 H.J. Lu <hongjiu.lu@intel.com> * config/i386/i386-protos.h (ix86_split_idivmod): New prototype. @@ -156,8 +1100,7 @@ alpha_override_options. * config/alpha/alpha-protos.h (override_options): Remove. * config/alpha/alpha.c (override_options): Rename to - alpha_option_override. Call SUBTARGET_OVERRIDE_OPTIONS. Make - static. + alpha_option_override. Call SUBTARGET_OVERRIDE_OPTIONS. Make static. (TARGET_OPTION_OVERRIDE): Define. * config/alpha/alpha.h (OVERRIDE_OPTIONS): Remove. * config/alpha/vms.h (SUBTARGET_OVERRIDE_OPTIONS): Define instead @@ -172,14 +1115,12 @@ (arm_override_options): Rename to arm_option_override. Make static. Call SUBTARGET_OVERRIDE_OPTIONS. * config/arm/arm.h (OVERRIDE_OPTIONS): Remove. - * config/arm/arm.md: Update comment referring to - arm_override_options. + * config/arm/arm.md: Update comment referring to arm_override_options. * config/arm/vxworks.h (SUBTARGET_OVERRIDE_OPTIONS): Define instead of OVERRIDE_OPTIONS. * config/avr/avr-protos.h (avr_override_options): Remove. * config/avr/avr.c (TARGET_OPTION_OVERRIDE): Define. - (avr_override_options): Rename to avr_option_override. Make - static. + (avr_override_options): Rename to avr_option_override. Make static. * config/avr/avr.h (OVERRIDE_OPTIONS): Remove. * config/bfin/bfin-protos.h (override_options): Remove (twice). * config/bfin/bfin.c (override_options): Rename to @@ -188,13 +1129,11 @@ * config/bfin/bfin.h (OVERRIDE_OPTIONS): Remove. * config/cris/cris-protos.h (cris_override_options): Remove. * config/cris/cris.c (TARGET_OPTION_OVERRIDE): Define. - (cris_override_options): Rename to cris_option_override. Make - static. + (cris_override_options): Rename to cris_option_override. Make static. * config/cris/cris.h (OVERRIDE_OPTIONS): Remove. * config/frv/frv-protos.h (frv_override_options): Remove. * config/frv/frv.c (TARGET_OPTION_OVERRIDE): Define. - (frv_override_options): Rename to frv_option_override. Make - static. + (frv_override_options): Rename to frv_option_override. Make static. * config/frv/frv.h (OVERRIDE_OPTIONS): Remove. * config/h8300/h8300-protos.h (h8300_init_once): Remove. * config/h8300/h8300.c (h8300_init_once): Rename to @@ -208,26 +1147,22 @@ (ix86_option_override): New. (TARGET_OPTION_OVERRIDE): Define. * config/i386/i386.h (OVERRIDE_OPTION): Remove. - * config/i386/linux64.h (DEFAULT_PCC_STRUCT_RETURN): Update - comment. + * config/i386/linux64.h (DEFAULT_PCC_STRUCT_RETURN): Update comment. * config/ia64/ia64.c (ia64_file_start): Update comment referring to ia64_override_options. * config/iq2000/iq2000-protos.h (override_options): Remove. * config/iq2000/iq2000.c (TARGET_OPTION_OVERRIDE): Define. - (override_options): Rename to iq2000_option_override. Make - static. + (override_options): Rename to iq2000_option_override. Make static. * config/iq2000/iq2000.h (OVERRIDE_OPTIONS): Remove. * config/lm32/lm32-protos.h (lm32_override_options): Remove. * config/lm32/lm32.c (TARGET_OPTION_OVERRIDE): Define. - (lm32_override_options): Rename to lm32_option_override. Make - static. + (lm32_override_options): Rename to lm32_option_override. Make static. * config/lm32/lm32.h (OVERRIDE_OPTIONS): Remove. * config/m32r/m32r.c (TARGET_OPTION_OVERRIDE): Define. (m32r_option_override): New. (m32r_init): Update comment. * config/m32r/m32r.h (OVERRIDE_OPTIONS): Remove. - * config/m68hc11/m68hc11-protos.h (m68hc11_override_options): - Remove. + * config/m68hc11/m68hc11-protos.h (m68hc11_override_options): Remove. * config/m68hc11/m68hc11.c (TARGET_OPTION_OVERRIDE): Define. (m68hc11_override_options): Rename to m68hc11_option_override. Make static. Return void. @@ -243,16 +1178,13 @@ * config/mcore/mcore.h (OVERRIDE_OPTIONS): Remove. * config/mep/mep-protos.h (mep_override_options): Remove. * config/mep/mep.c (TARGET_OPTION_OVERRIDE): Define. - (mep_override_options): Rename to mep_option_override. Make - static. + (mep_override_options): Rename to mep_option_override. Make static. * config/mep/mep.h (OVERRIDE_OPTIONS): Remove. * config/mmix/mmix-protos.h (mmix_override_options): Remove. * config/mmix/mmix.c (TARGET_OPTION_OVERRIDE): Define. - (mmix_override_options): Rename to mmix_option_override. Make - static. + (mmix_override_options): Rename to mmix_option_override. Make static. * config/mmix/mmix.h (OVERRIDE_OPTIONS): Remove. - * config/mn10300/mn10300-protos.h (mn10300_override_options): - Remove. + * config/mn10300/mn10300-protos.h (mn10300_override_options): Remove. * config/mn10300/mn10300.c (TARGET_OPTION_OVERRIDE): Define. (mn10300_override_options): Rename to mn10300_option_override. Make static. @@ -269,16 +1201,11 @@ Make static. Update comment and definition of TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE. * config/picochip/picochip.h (OVERRIDE_OPTIONS): Remove. - * config/rs6000/aix43.h (SUBTARGET_OVERRIDE_OPTIONS): Update - comment. - * config/rs6000/aix51.h (SUBTARGET_OVERRIDE_OPTIONS): Update - comment. - * config/rs6000/aix52.h (SUBTARGET_OVERRIDE_OPTIONS): Update - comment. - * config/rs6000/aix53.h (SUBTARGET_OVERRIDE_OPTIONS): Update - comment. - * config/rs6000/aix61.h (SUBTARGET_OVERRIDE_OPTIONS): Update - comment. + * config/rs6000/aix43.h (SUBTARGET_OVERRIDE_OPTIONS): Update comment. + * config/rs6000/aix51.h (SUBTARGET_OVERRIDE_OPTIONS): Update comment. + * config/rs6000/aix52.h (SUBTARGET_OVERRIDE_OPTIONS): Update comment. + * config/rs6000/aix53.h (SUBTARGET_OVERRIDE_OPTIONS): Update comment. + * config/rs6000/aix61.h (SUBTARGET_OVERRIDE_OPTIONS): Update comment. * config/rs6000/linux64.h (OPTION_TARGET_CPU_DEFAULT): Define instead of OVERRIDE_OPTIONS. * config/rs6000/rs6000-modes.def: Update comment referring to @@ -291,8 +1218,7 @@ (rs6000_option_override): New. * config/rs6000/rs6000.h (OPTION_TARGET_CPU_DEFAULT): Define instead of OVERRIDE_OPTIONS. - * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Update - comment. + * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Update comment. * config/s390/s390-protos.h (override_options): Remove. * config/s390/s390.c (override_options): Rename to s390_option_override. Make static. @@ -335,8 +1261,7 @@ * config/vxworks.h: Update comment referring to OVERRIDE_OPTIONS. * config/xtensa/xtensa-protos.h (override_options): Remove. * config/xtensa/xtensa.c (TARGET_OPTION_OVERRIDE): Define. - (override_options): Rename to xtensa_option_override. Make - static. + (override_options): Rename to xtensa_option_override. Make static. * config/xtensa/xtensa.h (OVERRIDE_OPTIONS): Remove. 2010-09-16 Richard Guenther <rguenther@suse.de> @@ -486,7 +1411,7 @@ 2010-09-15 Tejas Belagod <tejas.belagod@arm.com> * config/arm/neon.md (vec_pack_trunc_<mode>): Instruction - pattern for vmovn. Expansion in case of non + pattern for vmovn. Expansion in case of non -mvectorize-with-neon-quad. (neon_vec_pack_trunc_<mode>): Instruction pattern for vmovn for non- -mvectorize-with-neon-quad case. @@ -5311,7 +6236,7 @@ PR target/45142 * config/i386/sse.md (vec_set<mode>_0): Do not set mode attribute for alternative 2. - (vec_set<moode>_0 splitter): Use SSEMODE4S mode iterator to also + (vec_set<mode>_0 splitter): Use SSEMODE4S mode iterator to also split V4SI operands. 2010-08-01 Anatoly Sokolov <aesok@post.ru> diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 517eaea4138..a7072fed5cf 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20100916 +20100927 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 363d70e98ce..da61d437cbd 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -922,7 +922,7 @@ IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H) IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H) IPA_TYPE_ESCAPE_H = ipa-type-escape.h $(TREE_H) CGRAPH_H = cgraph.h $(VEC_H) $(TREE_H) $(BASIC_BLOCK_H) $(FUNCTION_H) \ - cif-code.def ipa-ref.h ipa-ref-inline.h + cif-code.def ipa-ref.h ipa-ref-inline.h $(LINKER_PLUGIN_API_H) DF_H = df.h $(BITMAP_H) $(REGSET_H) sbitmap.h $(BASIC_BLOCK_H) \ alloc-pool.h $(TIMEVAR_H) RESOURCE_H = resource.h hard-reg-set.h $(DF_H) @@ -1478,13 +1478,11 @@ OBJS-archive = \ OBJS = $(OBJS-common) $(OBJS-md) $(OBJS-archive) -OBJS-onestep = libbackend.o $(OBJS-archive) - # This lists all host objects for the front ends. ALL_HOST_FRONTEND_OBJS = $(C_OBJS) \ $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS)) -ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) libbackend.o \ +ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) \ @TREEBROWSER@ main.o gccspec.o version.o intl.o prefix.o cppspec.o \ $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) mips-tfile.o mips-tdump.o \ $(GCOV_OBJS) $(GCOV_DUMP_OBJS) @@ -1818,9 +1816,9 @@ rest.cross: specs compilations: $(BACKEND) # This archive is strictly for the host. -libbackend.a: $(OBJS@onestep@) +libbackend.a: $(OBJS) -rm -rf libbackend.a - $(AR) $(AR_FLAGS) libbackend.a $(OBJS@onestep@) + $(AR) $(AR_FLAGS) libbackend.a $(OBJS) -$(RANLIB) $(RANLIB_FLAGS) libbackend.a # We call this executable `xgcc' rather than `gcc' @@ -3229,7 +3227,7 @@ df-core.o : df-core.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ df-problems.o : df-problems.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(RTL_H) insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \ hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h $(TIMEVAR_H) \ - $(TM_P_H) $(FLAGS_H) output.h $(EXCEPT_H) dce.h vecprim.h + $(TM_P_H) $(TARGET_H) $(FLAGS_H) output.h $(EXCEPT_H) dce.h vecprim.h df-scan.o : df-scan.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ insn-config.h $(RECOG_H) $(FUNCTION_H) $(REGS_H) alloc-pool.h \ hard-reg-set.h $(BASIC_BLOCK_H) $(DF_H) $(BITMAP_H) sbitmap.h $(TIMEVAR_H) \ @@ -3583,19 +3581,6 @@ mips-tdump: mips-tdump.o version.o $(LIBDEPS) mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) coretypes.h \ $(TM_H) version.h $(srcdir)/../include/getopt.h stab.def -# FIXME: writing proper dependencies for this is a *LOT* of work. -libbackend.o : $(OBJS-common:.o=.c) $(out_file) \ - insn-config.h insn-flags.h insn-codes.h insn-constants.h \ - insn-attr.h $(DATESTAMP) $(BASEVER) $(DEVPHASE) gcov-iov.h - $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \ - -DTARGET_NAME=\"$(target_noncanonical)\" \ - -DLOCALEDIR=\"$(localedir)\" \ - -c $(filter %.c,$^) -o $@ \ - -DBASEVER=$(BASEVER_s) -DDATESTAMP=$(DATESTAMP_s) \ - -DREVISION=$(REVISION_s) \ - -DDEVPHASE=$(DEVPHASE_s) -DPKGVERSION=$(PKGVERSION_s) \ - -DBUGURL=$(BUGURL_s) -combine - # # Generate header and source files from the machine description, # and compile them. diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6624445ef15..42c3d3cd19b 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,90 @@ +2010-09-22 Joseph Myers <joseph@codesourcery.com> + + * gcc-interface/lang.opt (-all-warnings, -include-barrier, + -include-directory, -include-directory=, -no-standard-includes, + -no-standard-libraries): New. + +2010-09-20 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity): Replace calls to + build_array_type with calls to build_nonshared_array_type. + (substitute_in_type): Likewise. + * gcc-interface/misc.c (LANG_HOOKS_HASH_TYPES): Delete. + (LANG_HOOKS_TYPE_HASH_EQ): Define. + (gnat_post_options): Add 'static' keyword. + (gnat_type_hash_eq): New static function. + * gcc-interface/utils.c (fntype_same_flags_p): New function. + (create_subprog_type): Call it. + (create_index_type): Call build_nonshared_range_type and tidy up. + (create_range_type): Likewise. + * gcc-interface/gigi.h (fntype_same_flags_p): Declare. + +2010-09-19 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/trans.c (gnat_pushdecl): Do not do anything special + for PARM_DECLs. + (end_subprog_body): If the body is a BIND_EXPR, make its associated + block the top-level one. + (build_function_stub): Build a statement group for the whole function. + * gcc-interface/utils.c (Subprogram_Body_to_gnu): If copy-in/copy-out + is used, create the enclosing block early and process first the OUT + parameters. + +2010-09-19 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Enumeration_Type>: Do + not generate debug info for individual enumerators. + +2010-09-19 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Access_Type>: Use record + type instead of enumeral type as the dummy type built for the template + type of fat pointers. + +2010-09-19 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/gigi.h (get_elaboration_procedure): Declare. + (gnat_zaplevel): Likewise. + * gcc-interface/decl.c (gnat_to_gnu_entity): Do not force global + binding level for an external constant. + <E_Constant>: Force the local context and create a fake scope before + translating the defining expression of an external constant. + <object>: Treat external constants at the global level explicitly for + renaming declarations. + (elaborate_expression_1): Force the variable to be static if the + expression is global. + * gcc-interface/trans.c (get_elaboration_procedure): New function. + (call_to_gnu): Use it. + (gnat_to_gnu): Likewise. + <N_Object_Declaration>: Do not test Is_Public to force the creation of + an initialization variable. + (add_decl_expr): Discard the statement if the declaration is external. + * gcc-interface/utils.c (gnat_pushdecl): Do not put the declaration in + the current block if it is external. + (create_var_decl_1): Do not test Is_Public to set TREE_STATIC. + (gnat_zaplevel): New global function. + +2010-09-19 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity): Explicitly test _LEVEL + variables against zero in all cases. + (rest_of_type_decl_compilation): Likewise. + * gcc-interface/trans.c (gigi): Pass properly typed constants to + create_var_decl. + (call_to_gnu): Fix formatting. + (Handled_Sequence_Of_Statements_to_gnu): Likewise. + (Exception_Handler_to_gnu_zcx): Likewise. + (gnat_to_gnu) <N_Object_Declaration>: Short-circuit handling of + constant + expressions in presence of a freeze node. + +2010-09-19 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Constant>: Look into + expressions for external constants that are aggregates. + * gcc-interface/utils2.c (build_simple_component_ref): If the field + is an inherited component in an extension, look through the extension. + 2010-09-10 Vincent Celier <celier@adacore.com> * projects.texi: Add documentation for package extensions diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 75cdb849391..06698755b5e 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -357,10 +357,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) another compilation unit) public entities, show we are at global level for the purpose of computing scopes. Don't do this for components or discriminants since the relevant test is whether or not the record is - being defined. */ + being defined. Don't do this for constants either as we'll look into + their defining expression in the local context. */ if (!definition && kind != E_Component && kind != E_Discriminant + && kind != E_Constant && Is_Public (gnat_entity) && !Is_Statically_Allocated (gnat_entity)) force_global++, this_global = true; @@ -421,18 +423,37 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) } /* If we have an external constant that we are not defining, get the - expression that is was defined to represent. We may throw that - expression away later if it is not a constant. Do not retrieve the - expression if it is an aggregate or allocator, because in complex - instantiation contexts it may not be expanded */ + expression that is was defined to represent. We may throw it away + later if it is not a constant. But do not retrieve the expression + if it is an allocator because the designated type might be dummy + at this point. */ if (!definition - && Present (Expression (Declaration_Node (gnat_entity))) && !No_Initialization (Declaration_Node (gnat_entity)) - && (Nkind (Expression (Declaration_Node (gnat_entity))) - != N_Aggregate) - && (Nkind (Expression (Declaration_Node (gnat_entity))) - != N_Allocator)) - gnu_expr = gnat_to_gnu (Expression (Declaration_Node (gnat_entity))); + && Present (Expression (Declaration_Node (gnat_entity))) + && Nkind (Expression (Declaration_Node (gnat_entity))) + != N_Allocator) + { + bool went_into_elab_proc = false; + + /* The expression may contain N_Expression_With_Actions nodes and + thus object declarations from other units. In this case, even + though the expression will eventually be discarded since not a + constant, the declarations would be stuck either in the global + varpool or in the current scope. Therefore we force the local + context and create a fake scope that we'll zap at the end. */ + if (!current_function_decl) + { + current_function_decl = get_elaboration_procedure (); + went_into_elab_proc = true; + } + gnat_pushlevel (); + + gnu_expr = gnat_to_gnu (Expression (Declaration_Node (gnat_entity))); + + gnat_zaplevel (); + if (went_into_elab_proc) + current_function_decl = NULL_TREE; + } /* Ignore deferred constant definitions without address clause since they are processed fully in the front-end. If No_Initialization @@ -928,10 +949,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) that for the renaming. At the global level, we can only do this if we know no SAVE_EXPRs need be made, because the expression we return might be used in arbitrary conditional - branches so we must force the SAVE_EXPRs evaluation - immediately and this requires a function context. */ + branches so we must force the evaluation of the SAVE_EXPRs + immediately and this requires a proper function context. + Note that an external constant is at the global level. */ if (!Materialize_Entity (gnat_entity) - && (!global_bindings_p () + && (!((!definition && kind == E_Constant) + || global_bindings_p ()) || (staticp (gnu_expr) && !TREE_SIDE_EFFECTS (gnu_expr)))) { @@ -942,7 +965,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) { /* ??? No DECL_EXPR is created so we need to mark the expression manually lest it is shared. */ - if (global_bindings_p ()) + if ((!definition && kind == E_Constant) + || global_bindings_p ()) MARK_VISITED (maybe_stable_expr); gnu_decl = maybe_stable_expr; save_gnu_tree (gnat_entity, gnu_decl, true); @@ -1361,11 +1385,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) } /* If this is a renaming pointer, attach the renamed object to it and - register it if we are at top level. */ + register it if we are at the global level. Note that an external + constant is at the global level. */ if (TREE_CODE (gnu_decl) == VAR_DECL && renamed_obj) { SET_DECL_RENAMED_OBJECT (gnu_decl, renamed_obj); - if (global_bindings_p ()) + if ((!definition && kind == E_Constant) || global_bindings_p ()) { DECL_RENAMING_GLOBAL_P (gnu_decl) = 1; record_global_renaming_pointer (gnu_decl); @@ -1500,7 +1525,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) = create_var_decl (get_entity_name (gnat_literal), NULL_TREE, gnu_type, gnu_value, true, false, false, false, NULL, gnat_literal); - + /* Do not generate debug info for individual enumerators. */ + DECL_IGNORED_P (gnu_literal) = 1; save_gnu_tree (gnat_literal, gnu_literal, false); gnu_literal_list = tree_cons (DECL_NAME (gnu_literal), gnu_value, gnu_literal_list); @@ -2044,7 +2070,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* Now build the array type. */ for (index = ndim - 1; index >= 0; index--) { - tem = build_array_type (tem, gnu_index_types[index]); + tem = build_nonshared_array_type (tem, gnu_index_types[index]); TYPE_MULTI_ARRAY_P (tem) = (index > 0); if (array_type_has_nonaliased_component (tem, gnat_entity)) TYPE_NONALIASED_COMPONENT (tem) = 1; @@ -2377,7 +2403,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* Now build the array type. */ for (index = ndim - 1; index >= 0; index --) { - gnu_type = build_array_type (gnu_type, gnu_index_types[index]); + gnu_type = build_nonshared_array_type (gnu_type, + gnu_index_types[index]); TYPE_MULTI_ARRAY_P (gnu_type) = (index > 0); if (array_type_has_nonaliased_component (gnu_type, gnat_entity)) TYPE_NONALIASED_COMPONENT (gnu_type) = 1; @@ -2623,8 +2650,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnat_entity); gnu_type - = build_array_type (gnat_to_gnu_type (Component_Type (gnat_entity)), - gnu_index_type); + = build_nonshared_array_type (gnat_to_gnu_type + (Component_Type (gnat_entity)), + gnu_index_type); if (array_type_has_nonaliased_component (gnu_type, gnat_entity)) TYPE_NONALIASED_COMPONENT (gnu_type) = 1; relate_alias_sets (gnu_type, gnu_string_type, ALIAS_SET_COPY); @@ -3512,7 +3540,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) && TYPE_IS_DUMMY_P (TREE_TYPE (get_gnu_tree (gnat_desig_equiv)))) || (!in_main_unit - && defer_incomplete_level + && defer_incomplete_level != 0 && !present_gnu_tree (gnat_desig_equiv)) || (in_main_unit && is_from_limited_with @@ -3533,7 +3561,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_type = TYPE_POINTER_TO (gnu_desig_type); if (!gnu_type) { - tree gnu_template_type = make_node (ENUMERAL_TYPE); + tree gnu_template_type = make_node (RECORD_TYPE); tree gnu_ptr_template = build_pointer_type (gnu_template_type); tree gnu_array_type = make_node (ENUMERAL_TYPE); tree gnu_ptr_array = build_pointer_type (gnu_array_type); @@ -3596,7 +3624,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) access type may be the full view of a private type. Note that the unconstrained array case is handled above. */ || ((!in_main_unit || imported_p) - && defer_incomplete_level + && defer_incomplete_level != 0 && !present_gnu_tree (gnat_desig_equiv) && (Is_Record_Type (gnat_desig_rep) || Is_Array_Type (gnat_desig_rep))) @@ -3730,7 +3758,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) Besides, variants of this non-dummy type might have been created along the way. update_pointer_to is expected to properly take care of those situations. */ - if (!defer_incomplete_level && !is_from_limited_with_in_main_unit) + if (defer_incomplete_level == 0 + && !is_from_limited_with_in_main_unit) update_pointer_to (TYPE_MAIN_VARIANT (gnu_old_desig_type), gnat_to_gnu_type (gnat_desig_equiv)); else @@ -5047,7 +5076,7 @@ rest_of_type_decl_compilation (tree decl) { /* We need to defer finalizing the type if incomplete types are being deferred or if they are being processed. */ - if (defer_incomplete_level || defer_finalize_level) + if (defer_incomplete_level != 0 || defer_finalize_level != 0) VEC_safe_push (tree, heap, defer_finalize_list, decl); else rest_of_type_decl_compilation_no_defer (decl); @@ -5978,7 +6007,7 @@ elaborate_expression_1 (tree gnu_expr, Entity_Id gnat_entity, tree gnu_name, IDENTIFIER_POINTER (gnu_name)), NULL_TREE, TREE_TYPE (gnu_expr), gnu_expr, !need_debug, Is_Public (gnat_entity), - !definition, false, NULL, gnat_entity); + !definition, expr_global, NULL, gnat_entity); /* We only need to use this variable if we are in global context since GCC can do the right thing in the local case. */ @@ -8583,7 +8612,7 @@ substitute_in_type (tree t, tree f, tree r) if (component == TREE_TYPE (t) && domain == TYPE_DOMAIN (t)) return t; - nt = build_array_type (component, domain); + nt = build_nonshared_array_type (component, domain); TYPE_ALIGN (nt) = TYPE_ALIGN (t); TYPE_USER_ALIGN (nt) = TYPE_USER_ALIGN (t); SET_TYPE_MODE (nt, TYPE_MODE (t)); diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h index 767700f6f76..dd30b246bb9 100644 --- a/gcc/ada/gcc-interface/gigi.h +++ b/gcc/ada/gcc-interface/gigi.h @@ -259,6 +259,9 @@ extern void post_error_ne_tree_2 (const char *msg, Node_Id node, Entity_Id ent, if none. */ extern tree get_exception_label (char kind); +/* Return the decl for the current elaboration procedure. */ +extern tree get_elaboration_procedure (void); + /* If nonzero, pretend we are allocating at global level. */ extern int force_global; @@ -403,6 +406,7 @@ extern int global_bindings_p (void); /* Enter and exit a new binding level. */ extern void gnat_pushlevel (void); extern void gnat_poplevel (void); +extern void gnat_zaplevel (void); /* Set SUPERCONTEXT of the BLOCK for the current binding level to FNDECL and point FNDECL to this BLOCK. */ @@ -443,6 +447,9 @@ extern tree gnat_signed_type (tree type_node); transparently converted to each other. */ extern int gnat_types_compatible_p (tree t1, tree t2); +/* Return true if T, a FUNCTION_TYPE, has the specified list of flags. */ +extern bool fntype_same_flags_p (const_tree, tree, bool, bool, bool); + /* Create an expression whose value is that of EXPR, converted to type TYPE. The TREE_TYPE of the value is always TYPE. This function implements all reasonable diff --git a/gcc/ada/gcc-interface/lang.opt b/gcc/ada/gcc-interface/lang.opt index 586b0e6326e..3b9129b32cc 100644 --- a/gcc/ada/gcc-interface/lang.opt +++ b/gcc/ada/gcc-interface/lang.opt @@ -1,5 +1,5 @@ ; Options for the Ada front end. -; Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc. +; Copyright (C) 2003, 2007, 2008, 2010 Free Software Foundation, Inc. ; ; This file is part of GCC. ; @@ -25,6 +25,24 @@ Language Ada +-all-warnings +Ada Alias(Wall) + +-include-barrier +Ada Alias(I, -) + +-include-directory +Ada Separate Alias(I) + +-include-directory= +Ada Joined Alias(I) + +-no-standard-includes +Ada Alias(nostdinc) + +-no-standard-libraries +Ada Alias(nostdlib) + I Ada Joined Separate ; Documented for C diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c index 080e9884532..1167f0361e0 100644 --- a/gcc/ada/gcc-interface/misc.c +++ b/gcc/ada/gcc-interface/misc.c @@ -72,6 +72,7 @@ static void gnat_print_decl (FILE *, tree, int); static void gnat_print_type (FILE *, tree, int); static const char *gnat_printable_name (tree, int); static const char *gnat_dwarf_name (tree, int); +static bool gnat_type_hash_eq (const_tree, const_tree); static tree gnat_return_tree (tree); static void gnat_parse_file (int); static void internal_error_function (diagnostic_context *, @@ -98,8 +99,8 @@ static tree gnat_eh_personality (void); #define LANG_HOOKS_POST_OPTIONS gnat_post_options #undef LANG_HOOKS_PARSE_FILE #define LANG_HOOKS_PARSE_FILE gnat_parse_file -#undef LANG_HOOKS_HASH_TYPES -#define LANG_HOOKS_HASH_TYPES false +#undef LANG_HOOKS_TYPE_HASH_EQ +#define LANG_HOOKS_TYPE_HASH_EQ gnat_type_hash_eq #undef LANG_HOOKS_GETDECLS #define LANG_HOOKS_GETDECLS lhd_return_null_tree_v #undef LANG_HOOKS_PUSHDECL @@ -304,7 +305,7 @@ gnat_init_options (unsigned int decoded_options_count, /* Post-switch processing. */ -bool +static bool gnat_post_options (const char **pfilename ATTRIBUTE_UNUSED) { /* Excess precision other than "fast" requires front-end @@ -595,6 +596,20 @@ gnat_dwarf_name (tree decl, int verbosity ATTRIBUTE_UNUSED) return (const char *) IDENTIFIER_POINTER (DECL_NAME (decl)); } +/* Return true if types T1 and T2 are identical for type hashing purposes. + Called only after doing all language independent checks. At present, + this function is only called when both types are FUNCTION_TYPE. */ + +static bool +gnat_type_hash_eq (const_tree t1, const_tree t2) +{ + gcc_assert (TREE_CODE (t1) == FUNCTION_TYPE); + return fntype_same_flags_p (t1, TYPE_CI_CO_LIST (t2), + TYPE_RETURN_UNCONSTRAINED_P (t2), + TYPE_RETURN_BY_DIRECT_REF_P (t2), + TREE_ADDRESSABLE (t2)); +} + /* Do nothing (return the tree node passed). */ static tree diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index b4031896984..7031bfb447c 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -593,12 +593,14 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED, others_decl = create_var_decl (get_identifier ("OTHERS"), get_identifier ("__gnat_others_value"), - integer_type_node, 0, 1, 0, 1, 1, 0, Empty); + integer_type_node, NULL_TREE, true, false, true, false, + NULL, Empty); all_others_decl = create_var_decl (get_identifier ("ALL_OTHERS"), get_identifier ("__gnat_all_others_value"), - integer_type_node, 0, 1, 0, 1, 1, 0, Empty); + integer_type_node, NULL_TREE, true, false, true, false, + NULL, Empty); main_identifier_node = get_identifier ("main"); @@ -2453,40 +2455,48 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) begin_subprog_body (gnu_subprog_decl); - /* If there are Out parameters, we need to ensure that the return statement - properly copies them out. We do this by making a new block and converting - any inner return into a goto to a label at the end of the block. */ + /* If there are In Out or Out parameters, we need to ensure that the return + statement properly copies them out. We do this by making a new block and + converting any return into a goto to a label at the end of the block. */ gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type); - VEC_safe_push (tree, gc, gnu_return_label_stack, - gnu_cico_list - ? create_artificial_label (input_location) - : NULL_TREE); + if (gnu_cico_list) + { + VEC_safe_push (tree, gc, gnu_return_label_stack, + create_artificial_label (input_location)); + + start_stmt_group (); + gnat_pushlevel (); + + /* See whether there are parameters for which we don't have a GCC tree + yet. These must be Out parameters. Make a VAR_DECL for them and + put it into TYPE_CI_CO_LIST, which must contain an empty entry too. + We can match up the entries because TYPE_CI_CO_LIST is in the order + of the parameters. */ + for (gnat_param = First_Formal_With_Extras (gnat_subprog_id); + Present (gnat_param); + gnat_param = Next_Formal_With_Extras (gnat_param)) + if (!present_gnu_tree (gnat_param)) + { + tree gnu_cico_entry = gnu_cico_list; + + /* Skip any entries that have been already filled in; they must + correspond to In Out parameters. */ + while (gnu_cico_entry && TREE_VALUE (gnu_cico_entry)) + gnu_cico_entry = TREE_CHAIN (gnu_cico_entry); + + /* Do any needed references for padded types. */ + TREE_VALUE (gnu_cico_entry) + = convert (TREE_TYPE (TREE_PURPOSE (gnu_cico_entry)), + gnat_to_gnu_entity (gnat_param, NULL_TREE, 1)); + } + } + else + VEC_safe_push (tree, gc, gnu_return_label_stack, NULL_TREE); /* Get a tree corresponding to the code for the subprogram. */ start_stmt_group (); gnat_pushlevel (); - /* See if there are any parameters for which we don't yet have GCC entities. - These must be for Out parameters for which we will be making VAR_DECL - nodes here. Fill them in to TYPE_CI_CO_LIST, which must contain the empty - entry as well. We can match up the entries because TYPE_CI_CO_LIST is in - the order of the parameters. */ - for (gnat_param = First_Formal_With_Extras (gnat_subprog_id); - Present (gnat_param); - gnat_param = Next_Formal_With_Extras (gnat_param)) - if (!present_gnu_tree (gnat_param)) - { - /* Skip any entries that have been already filled in; they must - correspond to In Out parameters. */ - while (gnu_cico_list && TREE_VALUE (gnu_cico_list)) - gnu_cico_list = TREE_CHAIN (gnu_cico_list); - - /* Do any needed references for padded types. */ - TREE_VALUE (gnu_cico_list) - = convert (TREE_TYPE (TREE_PURPOSE (gnu_cico_list)), - gnat_to_gnu_entity (gnat_param, NULL_TREE, 1)); - } - /* On VMS, establish our condition handler to possibly turn a condition into the corresponding exception if the subprogram has a foreign convention or is exported. @@ -2511,6 +2521,40 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) gnat_poplevel (); gnu_result = end_stmt_group (); + /* If we are dealing with a return from an Ada procedure with parameters + passed by copy-in/copy-out, we need to return a record containing the + final values of these parameters. If the list contains only one entry, + return just that entry though. + + For a full description of the copy-in/copy-out parameter mechanism, see + the part of the gnat_to_gnu_entity routine dealing with the translation + of subprograms. + + We need to make a block that contains the definition of that label and + the copying of the return value. It first contains the function, then + the label and copy statement. */ + if (gnu_cico_list) + { + tree gnu_retval; + + add_stmt (gnu_result); + add_stmt (build1 (LABEL_EXPR, void_type_node, + VEC_last (tree, gnu_return_label_stack))); + + if (list_length (gnu_cico_list) == 1) + gnu_retval = TREE_VALUE (gnu_cico_list); + else + gnu_retval = build_constructor_from_list (TREE_TYPE (gnu_subprog_type), + gnu_cico_list); + + add_stmt_with_node (build_return_expr (gnu_result_decl, gnu_retval), + End_Label (Handled_Statement_Sequence (gnat_node))); + gnat_poplevel (); + gnu_result = end_stmt_group (); + } + + VEC_pop (tree, gnu_return_label_stack); + /* If we populated the parameter attributes cache, we need to make sure that the cached expressions are evaluated on all possible paths. */ cache = DECL_STRUCT_FUNCTION (gnu_subprog_decl)->language->parm_attr_cache; @@ -2535,43 +2579,6 @@ Subprogram_Body_to_gnu (Node_Id gnat_node) gnu_result = end_stmt_group (); } - /* If we are dealing with a return from an Ada procedure with parameters - passed by copy-in/copy-out, we need to return a record containing the - final values of these parameters. If the list contains only one entry, - return just that entry though. - - For a full description of the copy-in/copy-out parameter mechanism, see - the part of the gnat_to_gnu_entity routine dealing with the translation - of subprograms. - - We need to make a block that contains the definition of that label and - the copying of the return value. It first contains the function, then - the label and copy statement. */ - if (VEC_last (tree, gnu_return_label_stack)) - { - tree gnu_retval; - - start_stmt_group (); - gnat_pushlevel (); - add_stmt (gnu_result); - add_stmt (build1 (LABEL_EXPR, void_type_node, - VEC_last (tree, gnu_return_label_stack))); - - gnu_cico_list = TYPE_CI_CO_LIST (gnu_subprog_type); - if (list_length (gnu_cico_list) == 1) - gnu_retval = TREE_VALUE (gnu_cico_list); - else - gnu_retval = build_constructor_from_list (TREE_TYPE (gnu_subprog_type), - gnu_cico_list); - - add_stmt_with_node (build_return_expr (gnu_result_decl, gnu_retval), - End_Label (Handled_Statement_Sequence (gnat_node))); - gnat_poplevel (); - gnu_result = end_stmt_group (); - } - - VEC_pop (tree, gnu_return_label_stack); - /* Set the end location. */ Sloc_to_locus ((Present (End_Label (Handled_Statement_Sequence (gnat_node))) @@ -2673,7 +2680,7 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) so we can give them the scope of the elaboration routine at top level. */ else if (!current_function_decl) { - current_function_decl = VEC_last (tree, gnu_elab_proc_stack); + current_function_decl = get_elaboration_procedure (); went_into_elab_proc = true; } @@ -2788,8 +2795,8 @@ call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target) /* Create an explicit temporary holding the copy. This ensures that its lifetime is as narrow as possible around a statement. */ gnu_temp = create_var_decl (create_tmp_var_name ("A"), NULL_TREE, - TREE_TYPE (gnu_name), NULL_TREE, false, - false, false, false, NULL, Empty); + TREE_TYPE (gnu_name), NULL_TREE, + false, false, false, false, NULL, Empty); DECL_ARTIFICIAL (gnu_temp) = 1; DECL_IGNORED_P (gnu_temp) = 1; @@ -3210,8 +3217,8 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node) gnu_jmpsave_decl = create_var_decl (get_identifier ("JMPBUF_SAVE"), NULL_TREE, jmpbuf_ptr_type, build_call_0_expr (get_jmpbuf_decl), - false, false, false, false, NULL, - gnat_node); + false, false, false, false, + NULL, gnat_node); DECL_ARTIFICIAL (gnu_jmpsave_decl) = 1; /* The __builtin_setjmp receivers will immediately reinstall it. Now @@ -3220,8 +3227,8 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node) it is uninitialized, although they will never be actually taken. */ TREE_NO_WARNING (gnu_jmpsave_decl) = 1; gnu_jmpbuf_decl = create_var_decl (get_identifier ("JMP_BUF"), - NULL_TREE, jmpbuf_type, - NULL_TREE, false, false, false, false, + NULL_TREE, jmpbuf_type, NULL_TREE, + false, false, false, false, NULL, gnat_node); DECL_ARTIFICIAL (gnu_jmpbuf_decl) = 1; @@ -3273,12 +3280,11 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node) gnat_pushlevel (); VEC_safe_push (tree, gc, gnu_except_ptr_stack, - create_var_decl (get_identifier ("EXCEPT_PTR"), - NULL_TREE, + create_var_decl (get_identifier ("EXCEPT_PTR"), NULL_TREE, build_pointer_type (except_type_node), build_call_0_expr (get_excptr_decl), - false, - false, false, false, NULL, gnat_node)); + false, false, false, false, + NULL, gnat_node)); /* Generate code for each handler. The N_Exception_Handler case does the real work and returns a COND_EXPR for each handler, which we chain @@ -3537,8 +3543,8 @@ Exception_Handler_to_gnu_zcx (Node_Id gnat_node) 1, integer_zero_node); gnu_incoming_exc_ptr = create_var_decl (get_identifier ("EXPTR"), NULL_TREE, ptr_type_node, gnu_current_exc_ptr, - false, false, false, false, NULL, - gnat_node); + false, false, false, false, + NULL, gnat_node); add_stmt_with_node (build_call_1_expr (begin_handler_decl, gnu_incoming_exc_ptr), @@ -3754,11 +3760,13 @@ gnat_to_gnu (Node_Id gnat_node) || kind == N_Handled_Sequence_Of_Statements || (IN (kind, N_Raise_xxx_Error) && Ekind (Etype (gnat_node)) == E_Void)) { + tree current_elab_proc = get_elaboration_procedure (); + /* If this is a statement and we are at top level, it must be part of the elaboration procedure, so mark us as being in that procedure. */ if (!current_function_decl) { - current_function_decl = VEC_last (tree, gnu_elab_proc_stack); + current_function_decl = current_elab_proc; went_into_elab_proc = true; } @@ -3769,7 +3777,7 @@ gnat_to_gnu (Node_Id gnat_node) every nested real statement instead. This also avoids triggering spurious errors on dummy (empty) sequences created by the front-end for package bodies in some cases. */ - if (current_function_decl == VEC_last (tree, gnu_elab_proc_stack) + if (current_function_decl == current_elab_proc && kind != N_Handled_Sequence_Of_Statements) Check_Elaboration_Code_Allowed (gnat_node); } @@ -3997,13 +4005,14 @@ gnat_to_gnu (Node_Id gnat_node) is frozen. */ if (Present (Freeze_Node (gnat_temp))) { - if ((Is_Public (gnat_temp) || global_bindings_p ()) - && !TREE_CONSTANT (gnu_expr)) + if (TREE_CONSTANT (gnu_expr)) + ; + else if (global_bindings_p ()) gnu_expr = create_var_decl (create_concat_name (gnat_temp, "init"), - NULL_TREE, TREE_TYPE (gnu_expr), - gnu_expr, false, Is_Public (gnat_temp), - false, false, NULL, gnat_temp); + NULL_TREE, TREE_TYPE (gnu_expr), gnu_expr, + false, false, false, false, + NULL, gnat_temp); else gnu_expr = gnat_save_expr (gnu_expr); @@ -5805,7 +5814,7 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity) || TREE_CODE (type) == QUAL_UNION_TYPE)) MARK_VISITED (TYPE_ADA_SIZE (type)); } - else + else if (!DECL_EXTERNAL (gnu_decl)) add_stmt_with_node (gnu_stmt, gnat_entity); /* If this is a variable and an initializer is attached to it, it must be @@ -7661,4 +7670,12 @@ get_exception_label (char kind) return NULL_TREE; } +/* Return the decl for the current elaboration procedure. */ + +tree +get_elaboration_procedure (void) +{ + return VEC_last (tree, gnu_elab_proc_stack); +} + #include "gt-ada-trans.h" diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index cadc4d7c0da..3fab92b0c1e 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -411,6 +411,22 @@ gnat_poplevel (void) free_binding_level = level; } +/* Exit a binding level and discard the associated BLOCK. */ + +void +gnat_zaplevel (void) +{ + struct gnat_binding_level *level = current_binding_level; + tree block = level->block; + + BLOCK_CHAIN (block) = free_block_chain; + free_block_chain = block; + + /* Free this binding structure. */ + current_binding_level = level->chain; + level->chain = free_binding_level; + free_binding_level = level; +} /* Records a ..._DECL node DECL as belonging to the current lexical scope and uses GNAT_NODE for location information and propagating flags. */ @@ -441,13 +457,12 @@ gnat_pushdecl (tree decl, Node_Id gnat_node) add_decl_expr (decl, gnat_node); /* Put the declaration on the list. The list of declarations is in reverse - order. The list will be reversed later. Put global variables in the - globals list and builtin functions in a dedicated list to speed up - further lookups. Don't put TYPE_DECLs for UNCONSTRAINED_ARRAY_TYPE into - the list, as they will cause trouble with the debugger and aren't needed - anyway. */ - if (TREE_CODE (decl) != TYPE_DECL - || TREE_CODE (TREE_TYPE (decl)) != UNCONSTRAINED_ARRAY_TYPE) + order. The list will be reversed later. Put global declarations in the + globals list and local ones in the current block. But skip TYPE_DECLs + for UNCONSTRAINED_ARRAY_TYPE in both cases, as they will cause trouble + with the debugger and aren't needed anyway. */ + if (!(TREE_CODE (decl) == TYPE_DECL + && TREE_CODE (TREE_TYPE (decl)) == UNCONSTRAINED_ARRAY_TYPE)) { if (global_bindings_p ()) { @@ -456,16 +471,10 @@ gnat_pushdecl (tree decl, Node_Id gnat_node) if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)) VEC_safe_push (tree, gc, builtin_decls, decl); } - else + else if (!DECL_EXTERNAL (decl)) { - tree block; - /* Fake PARM_DECLs go into the topmost block of the function. */ - if (TREE_CODE (decl) == PARM_DECL) - block = BLOCK_SUPERCONTEXT (current_binding_level->block); - else - block = current_binding_level->block; - DECL_CHAIN (decl) = BLOCK_VARS (block); - BLOCK_VARS (block) = decl; + DECL_CHAIN (decl) = BLOCK_VARS (current_binding_level->block); + BLOCK_VARS (current_binding_level->block) = decl; } } @@ -1097,10 +1106,8 @@ create_subprog_type (tree return_type, tree param_decl_list, tree cico_list, /* TYPE may have been shared since GCC hashes types. If it has a different CICO_LIST, make a copy. Likewise for the various flags. */ - if (TYPE_CI_CO_LIST (type) != cico_list - || TYPE_RETURN_UNCONSTRAINED_P (type) != return_unconstrained_p - || TYPE_RETURN_BY_DIRECT_REF_P (type) != return_by_direct_ref_p - || TREE_ADDRESSABLE (type) != return_by_invisi_ref_p) + if (!fntype_same_flags_p (type, cico_list, return_unconstrained_p, + return_by_direct_ref_p, return_by_invisi_ref_p)) { type = copy_type (type); TYPE_CI_CO_LIST (type) = cico_list; @@ -1156,17 +1163,9 @@ tree create_index_type (tree min, tree max, tree index, Node_Id gnat_node) { /* First build a type for the desired range. */ - tree type = build_range_type (sizetype, min, max); - - /* If this type has the TYPE_INDEX_TYPE we want, return it. */ - if (TYPE_INDEX_TYPE (type) == index) - return type; - - /* Otherwise, if TYPE_INDEX_TYPE is set, make a copy. Note that we have - no way of sharing these types, but that's only a small hole. */ - if (TYPE_INDEX_TYPE (type)) - type = copy_type (type); + tree type = build_nonshared_range_type (sizetype, min, max); + /* Then set the index type. */ SET_TYPE_INDEX_TYPE (type, index); create_type_decl (NULL_TREE, type, NULL, true, false, gnat_node); @@ -1185,26 +1184,12 @@ create_range_type (tree type, tree min, tree max) type = sizetype; /* First build a type with the base range. */ - range_type - = build_range_type (type, TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type)); - - min = convert (type, min); - max = convert (type, max); - - /* If this type has the TYPE_RM_{MIN,MAX}_VALUE we want, return it. */ - if (TYPE_RM_MIN_VALUE (range_type) - && TYPE_RM_MAX_VALUE (range_type) - && operand_equal_p (TYPE_RM_MIN_VALUE (range_type), min, 0) - && operand_equal_p (TYPE_RM_MAX_VALUE (range_type), max, 0)) - return range_type; - - /* Otherwise, if TYPE_RM_{MIN,MAX}_VALUE is set, make a copy. */ - if (TYPE_RM_MIN_VALUE (range_type) || TYPE_RM_MAX_VALUE (range_type)) - range_type = copy_type (range_type); + range_type = build_nonshared_range_type (type, TYPE_MIN_VALUE (type), + TYPE_MAX_VALUE (type)); /* Then set the actual range. */ - SET_TYPE_RM_MIN_VALUE (range_type, min); - SET_TYPE_RM_MAX_VALUE (range_type, max); + SET_TYPE_RM_MIN_VALUE (range_type, convert (type, min)); + SET_TYPE_RM_MAX_VALUE (range_type, convert (type, max)); return range_type; } @@ -1371,12 +1356,11 @@ create_var_decl_1 (tree var_name, tree asm_name, tree type, tree var_init, && !have_global_bss_p ()) DECL_COMMON (var_decl) = 1; - /* If it's public and not external, always allocate storage for it. - At the global binding level we need to allocate static storage for the - variable if and only if it's not external. If we are not at the top level - we allocate automatic storage unless requested not to. */ + /* At the global binding level, we need to allocate static storage for the + variable if it isn't external. Otherwise, we allocate automatic storage + unless requested not to. */ TREE_STATIC (var_decl) - = !extern_flag && (public_flag || static_flag || global_bindings_p ()); + = !extern_flag && (static_flag || global_bindings_p ()); /* For an external constant whose initializer is not absolute, do not emit debug info. In DWARF this would mean a global relocation in a read-only @@ -1893,6 +1877,13 @@ end_subprog_body (tree body) /* Mark the RESULT_DECL as being in this subprogram. */ DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl; + /* The body should be a BIND_EXPR whose BLOCK is the top-level one. */ + if (TREE_CODE (body) == BIND_EXPR) + { + BLOCK_SUPERCONTEXT (BIND_EXPR_BLOCK (body)) = fndecl; + DECL_INITIAL (fndecl) = BIND_EXPR_BLOCK (body); + } + DECL_SAVED_TREE (fndecl) = body; current_function_decl = DECL_CONTEXT (fndecl); @@ -2106,6 +2097,18 @@ gnat_types_compatible_p (tree t1, tree t2) return 0; } + +/* Return true if T, a FUNCTION_TYPE, has the specified list of flags. */ + +bool +fntype_same_flags_p (const_tree t, tree cico_list, bool return_unconstrained_p, + bool return_by_direct_ref_p, bool return_by_invisi_ref_p) +{ + return TYPE_CI_CO_LIST (t) == cico_list + && TYPE_RETURN_UNCONSTRAINED_P (t) == return_unconstrained_p + && TYPE_RETURN_BY_DIRECT_REF_P (t) == return_by_direct_ref_p + && TREE_ADDRESSABLE (t) == return_by_invisi_ref_p; +} /* EXP is an expression for the size of an object. If this size contains discriminant references, replace them with the maximum (if MAX_P) or @@ -3214,15 +3217,18 @@ build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog) tree gnu_subprog_type, gnu_subprog_addr, gnu_subprog_call; tree gnu_stub_param, gnu_arg_types, gnu_param; tree gnu_stub_decl = DECL_FUNCTION_STUB (gnu_subprog); - tree gnu_body; VEC(tree,gc) *gnu_param_vec = NULL; gnu_subprog_type = TREE_TYPE (gnu_subprog); + /* Initialize the information structure for the function. */ + allocate_struct_function (gnu_stub_decl, false); + set_cfun (NULL); + begin_subprog_body (gnu_stub_decl); - gnat_pushlevel (); start_stmt_group (); + gnat_pushlevel (); /* Loop over the parameters of the stub and translate any of them passed by descriptor into a by reference one. */ @@ -3244,8 +3250,6 @@ build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog) VEC_safe_push (tree, gc, gnu_param_vec, gnu_param); } - gnu_body = end_stmt_group (); - /* Invoke the internal subprogram. */ gnu_subprog_addr = build1 (ADDR_EXPR, build_pointer_type (gnu_subprog_type), gnu_subprog); @@ -3254,16 +3258,13 @@ build_function_stub (tree gnu_subprog, Entity_Id gnat_subprog) /* Propagate the return value, if any. */ if (VOID_TYPE_P (TREE_TYPE (gnu_subprog_type))) - append_to_statement_list (gnu_subprog_call, &gnu_body); + add_stmt (gnu_subprog_call); else - append_to_statement_list (build_return_expr (DECL_RESULT (gnu_stub_decl), - gnu_subprog_call), - &gnu_body); + add_stmt (build_return_expr (DECL_RESULT (gnu_stub_decl), + gnu_subprog_call)); gnat_poplevel (); - - allocate_struct_function (gnu_stub_decl, false); - end_subprog_body (gnu_body); + end_subprog_body (end_stmt_group ()); } /* Build a type to be used to represent an aliased object whose nominal type diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c index bd78686e240..c40223f8e36 100644 --- a/gcc/ada/gcc-interface/utils2.c +++ b/gcc/ada/gcc-interface/utils2.c @@ -1603,10 +1603,9 @@ build_simple_component_ref (tree record_variable, tree component, if (!field) return NULL_TREE; - /* If this field is not in the specified record, see if we can find - something in the record whose original field is the same as this one. */ + /* If this field is not in the specified record, see if we can find a field + in the specified record whose original field is the same as this one. */ if (DECL_CONTEXT (field) != record_type) - /* Check if there is a field with name COMPONENT in the record. */ { tree new_field; @@ -1616,6 +1615,21 @@ build_simple_component_ref (tree record_variable, tree component, if (SAME_FIELD_P (field, new_field)) break; + /* Next, see if we're looking for an inherited component in an extension. + If so, look thru the extension directly. */ + if (!new_field + && TREE_CODE (record_variable) == VIEW_CONVERT_EXPR + && TYPE_ALIGN_OK (record_type) + && TREE_CODE (TREE_TYPE (TREE_OPERAND (record_variable, 0))) + == RECORD_TYPE + && TYPE_ALIGN_OK (TREE_TYPE (TREE_OPERAND (record_variable, 0)))) + { + ref = build_simple_component_ref (TREE_OPERAND (record_variable, 0), + NULL_TREE, field, no_fold_p); + if (ref) + return ref; + } + /* Next, loop thru DECL_INTERNAL_P components if we haven't found the component in the first search. Doing this search in 2 steps is required to avoiding hidden homonymous fields in the diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 692ebe65cc4..e274d6c044f 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -246,7 +246,13 @@ enum bb_flags /* Set on blocks that cannot be threaded through. Only used in cfgcleanup.c. */ - BB_NONTHREADABLE_BLOCK = 1 << 11 + BB_NONTHREADABLE_BLOCK = 1 << 11, + + /* Set on blocks that were modified in some way. This bit is set in + df_set_bb_dirty, but not cleared by df_analyze, so it can be used + to test whether a block has been modified prior to a df_analyze + call. */ + BB_MODIFIED = 1 << 12 }; /* Dummy flag for convenience in the hot/cold partitioning code. */ diff --git a/gcc/builtins.c b/gcc/builtins.c index 2dd6119c782..384a81a035b 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -8555,12 +8555,21 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, STRIP_NOPS (srcvar); if (TREE_CODE (srcvar) == ADDR_EXPR && var_decl_component_p (TREE_OPERAND (srcvar, 0)) - && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len) - && (!STRICT_ALIGNMENT - || !destvar - || src_align >= TYPE_ALIGN (desttype))) - srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype, - srcvar, off0); + && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)) + { + if (!destvar + || src_align >= TYPE_ALIGN (desttype)) + srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype, + srcvar, off0); + else if (!STRICT_ALIGNMENT) + { + srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype), + src_align); + srcvar = fold_build2 (MEM_REF, srctype, srcvar, off0); + } + else + srcvar = NULL_TREE; + } else srcvar = NULL_TREE; @@ -8569,19 +8578,31 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src, if (srcvar == NULL_TREE) { - if (STRICT_ALIGNMENT - && src_align < TYPE_ALIGN (desttype)) - return NULL_TREE; STRIP_NOPS (src); - srcvar = fold_build2 (MEM_REF, desttype, src, off0); + if (src_align >= TYPE_ALIGN (desttype)) + srcvar = fold_build2 (MEM_REF, desttype, src, off0); + else + { + if (STRICT_ALIGNMENT) + return NULL_TREE; + srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype), + src_align); + srcvar = fold_build2 (MEM_REF, srctype, src, off0); + } } else if (destvar == NULL_TREE) { - if (STRICT_ALIGNMENT - && dest_align < TYPE_ALIGN (srctype)) - return NULL_TREE; STRIP_NOPS (dest); - destvar = fold_build2 (MEM_REF, srctype, dest, off0); + if (dest_align >= TYPE_ALIGN (srctype)) + destvar = fold_build2 (MEM_REF, srctype, dest, off0); + else + { + if (STRICT_ALIGNMENT) + return NULL_TREE; + desttype = build_aligned_type (TYPE_MAIN_VARIANT (srctype), + dest_align); + destvar = fold_build2 (MEM_REF, desttype, dest, off0); + } } expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar); diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 6c65b27e004..35f3d29664e 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -1203,15 +1203,14 @@ pop_scope (void) DECL_CHAIN (extp) = BLOCK_VARS (block); BLOCK_VARS (block) = extp; } - /* If this is the file scope, and we are processing more - than one translation unit in this compilation, set - DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL. - This makes same_translation_unit_p work, and causes - static declarations to be given disambiguating suffixes. */ - if (scope == file_scope && num_in_fnames > 1) + /* If this is the file scope set DECL_CONTEXT of each decl to + the TRANSLATION_UNIT_DECL. This makes same_translation_unit_p + work. */ + if (scope == file_scope) { DECL_CONTEXT (p) = context; - if (TREE_CODE (p) == TYPE_DECL) + if (TREE_CODE (p) == TYPE_DECL + && TREE_TYPE (p) != error_mark_node) set_type_context (TREE_TYPE (p), context); } @@ -6718,6 +6717,17 @@ detect_field_duplicates (tree fieldlist) tree x, y; int timeout = 10; + /* If the struct is the list of instance variables of an Objective-C + class, then we need to add all the instance variables of + superclasses before checking for duplicates (since you can't have + an instance variable in a subclass with the same name as an + instance variable in a superclass). objc_get_interface_ivars() + leaves fieldlist unchanged if we are not in this case, so in that + case nothing changes compared to C. + */ + if (c_dialect_objc ()) + fieldlist = objc_get_interface_ivars (fieldlist); + /* First, see if there are more than "a few" fields. This is trivially true if there are zero or one fields. */ if (!fieldlist) diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 7d5821c4fe8..7d3e3dddf7c 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,40 @@ +2010-09-24 Jan Hubicka <jh@suse.cz> + + * c-common.c (handle_leaf_attribute): New function. + (struct attribute_spec c_common_att): Add leaf. + +2010-09-22 Joseph Myers <joseph@codesourcery.com> + + * c.opt (-all-warnings, -ansi, -assert, -assert=, -comments, + -comments-in-macros, -define-macro, -define-macro=, -dependencies, + -dump, -dump=, -imacros, -imacros=, -include, -include=, + -include-barrier, -include-directory, -include-directory=, + -include-directory-after, -include-directory-after=, + -include-prefix, -include-prefix=, -include-with-prefix, + -include-with-prefix=, -include-with-prefix-after, + -include-with-prefix-after=, -include-with-prefix-before, + -include-with-prefix-before=, -no-integrated-cpp, + -no-line-commands, -no-standard-includes, -no-warnings, -output, + -output=, -pedantic, -pedantic-errors, -preprocess, + -print-missing-file-dependencies, -trace-includes, -traditional, + -traditional-cpp, -trigraphs, -undefine-macro, -undefine-macro=, + -user-dependencies, -verbose, -write-dependencies, + -write-user-dependencies, no-integrated-cpp, traditional): New. + +2010-09-21 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/23710 + * c-common.h (objc_start_method_definition): Return bool instead + of void. + * stub-objc.c (objc_start_method_definition): Return bool instead + of void. + +2010-09-21 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/25965 + * c-common.h (objc_get_interface_ivars): New declaration. + * stub-objc.c (objc_get_interface_ivars): New stub. + 2010-09-15 Ian Lance Taylor <iant@google.com> * c-common.c (parse_optimize_options): Do not capitalize warning diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index cf2fe17ee66..6ef3bf99542 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -308,6 +308,7 @@ static tree handle_hot_attribute (tree *, tree, tree, int, bool *); static tree handle_cold_attribute (tree *, tree, tree, int, bool *); static tree handle_noinline_attribute (tree *, tree, tree, int, bool *); static tree handle_noclone_attribute (tree *, tree, tree, int, bool *); +static tree handle_leaf_attribute (tree *, tree, tree, int, bool *); static tree handle_always_inline_attribute (tree *, tree, tree, int, bool *); static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *); @@ -570,6 +571,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_noinline_attribute }, { "noclone", 0, 0, true, false, false, handle_noclone_attribute }, + { "leaf", 0, 0, true, false, false, + handle_leaf_attribute }, { "always_inline", 0, 0, true, false, false, handle_always_inline_attribute }, { "gnu_inline", 0, 0, true, false, false, @@ -5873,6 +5876,28 @@ handle_gnu_inline_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle a "leaf" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_leaf_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + if (!TREE_PUBLIC (*node)) + { + warning (OPT_Wattributes, "%qE attribute has no effect on unit local functions", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Handle an "artificial" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 6118f518bc6..de72c192edf 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -561,7 +561,7 @@ extern int flag_hosted; extern int print_struct_values; -/* ???. Undocumented. */ +/* Tells the compiler what is the constant string class for ObjC. */ extern const char *constant_string_class_name; @@ -962,6 +962,7 @@ extern tree objc_build_string_object (tree); extern tree objc_get_protocol_qualified_type (tree, tree); extern tree objc_get_class_reference (tree); extern tree objc_get_class_ivars (tree); +extern tree objc_get_interface_ivars (tree); extern void objc_start_class_interface (tree, tree, tree); extern void objc_start_category_interface (tree, tree, tree); extern void objc_start_protocol (tree, tree); @@ -975,7 +976,7 @@ extern void objc_set_visibility (int); extern void objc_set_method_type (enum tree_code); extern tree objc_build_method_signature (tree, tree, tree, bool); extern void objc_add_method_declaration (tree); -extern void objc_start_method_definition (tree); +extern bool objc_start_method_definition (tree); extern void objc_finish_method_definition (tree); extern void objc_add_instance_variable (tree); extern tree objc_build_keyword_decl (tree, tree, tree); diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index a997f79cf8c..f91eeef5a31 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -34,9 +34,153 @@ C++ Language ObjC++ +-all-warnings +C ObjC C++ ObjC++ Warning Alias(Wall) + +-ansi +C ObjC C++ ObjC++ Alias(ansi) + +-assert +C ObjC C++ ObjC++ Separate Alias(A) MissingArgError(assertion missing after %qs) + +-assert= +C ObjC C++ ObjC++ Joined Alias(A) MissingArgError(assertion missing after %qs) + +-comments +C ObjC C++ ObjC++ Alias(C) + +-comments-in-macros +C ObjC C++ ObjC++ Alias(CC) + +-define-macro +C ObjC C++ ObjC++ Separate Alias(D) MissingArgError(macro name missing after %qs) + +-define-macro= +C ObjC C++ ObjC++ Joined Alias(D) MissingArgError(macro name missing after %qs) + +-dependencies +C ObjC C++ ObjC++ Alias(M) + +-dump +C ObjC C++ ObjC++ Separate Alias(d) + +-dump= +C ObjC C++ ObjC++ Joined Alias(d) + +-imacros +C ObjC C++ ObjC++ Separate Alias(imacros) MissingArgError(missing filename after %qs) + +-imacros= +C ObjC C++ ObjC++ Joined Alias(imacros) MissingArgError(missing filename after %qs) + +-include +C ObjC C++ ObjC++ Separate Alias(include) MissingArgError(missing filename after %qs) + +-include= +C ObjC C++ ObjC++ Joined Alias(include) MissingArgError(missing filename after %qs) + +-include-barrier +C ObjC C++ ObjC++ Alias(I, -) + +-include-directory +C ObjC C++ ObjC++ Separate Alias(I) MissingArgError(missing path after %qs) + +-include-directory= +C ObjC C++ ObjC++ Joined Alias(I) MissingArgError(missing path after %qs) + +-include-directory-after +C ObjC C++ ObjC++ Separate Alias(idirafter) MissingArgError(missing path after %qs) + +-include-directory-after= +C ObjC C++ ObjC++ Joined Alias(idirafter) MissingArgError(missing path after %qs) + +-include-prefix +C ObjC C++ ObjC++ Separate Alias(iprefix) + +-include-prefix= +C ObjC C++ ObjC++ JoinedOrMissing Alias(iprefix) + +-include-with-prefix +C ObjC C++ ObjC++ Separate Alias(iwithprefix) + +-include-with-prefix= +C ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefix) + +-include-with-prefix-after +C ObjC C++ ObjC++ Separate Alias(iwithprefix) + +-include-with-prefix-after= +C ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefix) + +-include-with-prefix-before +C ObjC C++ ObjC++ Separate Alias(iwithprefixbefore) + +-include-with-prefix-before= +C ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefixbefore) + +-no-integrated-cpp +Driver Alias(no-integrated-cpp) + +-no-line-commands +C ObjC C++ ObjC++ Alias(P) + +-no-standard-includes +C ObjC C++ ObjC++ Alias(nostdinc) + +-no-warnings +C ObjC C++ ObjC++ Alias(w) + +-output +C ObjC C++ ObjC++ Separate Alias(o) + +-output= +C ObjC C++ ObjC++ Joined Alias(o) + -output-pch= C ObjC C++ ObjC++ Joined Separate +-pedantic +C ObjC C++ ObjC++ Alias(pedantic) + +-pedantic-errors +C ObjC C++ ObjC++ Alias(pedantic-errors) + +-preprocess +C ObjC C++ ObjC++ Undocumented Alias(E) + +-print-missing-file-dependencies +C ObjC C++ ObjC++ Alias(MG) + +-trace-includes +C ObjC C++ ObjC++ Alias(H) + +-traditional +Driver Alias(traditional) + +-traditional-cpp +C ObjC C++ ObjC++ Alias(traditional-cpp) + +-trigraphs +C ObjC C++ ObjC++ Alias(trigraphs) + +-undefine-macro +C ObjC C++ ObjC++ Separate Alias(U) MissingArgError(macro name missing after %qs) + +-undefine-macro= +C ObjC C++ ObjC++ Joined Alias(U) MissingArgError(macro name missing after %qs) + +-user-dependencies +C ObjC C++ ObjC++ Alias(MM) + +-verbose +Common C ObjC C++ ObjC++ Alias(v) + +-write-dependencies +C ObjC C++ ObjC++ NoDriverArg Separate Alias(MD) MissingArgError(missing filename after %qs) + +-write-user-dependencies +C ObjC C++ ObjC++ NoDriverArg Separate Alias(MMD) MissingArgError(missing filename after %qs) + A C ObjC C++ ObjC++ Joined Separate MissingArgError(assertion missing after %qs) -A<question>=<answer> Assert the <answer> to <question>. Putting '-' before <question> disables the <answer> to <question> @@ -932,6 +1076,9 @@ C ObjC C++ ObjC++ Joined Separate lang-asm C Undocumented RejectDriver +no-integrated-cpp +Driver + nostdinc C ObjC C++ ObjC++ Do not search standard system include directories (those specified with -isystem will still be used) @@ -1038,6 +1185,9 @@ std=iso9899:199x C ObjC Alias(std=c99) Deprecated in favor of -std=iso9899:1999 +traditional +Driver + traditional-cpp C ObjC C++ ObjC++ Enable traditional preprocessing diff --git a/gcc/c-family/stub-objc.c b/gcc/c-family/stub-objc.c index b7748f79c6e..0ce1feffb41 100644 --- a/gcc/c-family/stub-objc.c +++ b/gcc/c-family/stub-objc.c @@ -184,9 +184,10 @@ objc_add_method_declaration (tree ARG_UNUSED (signature)) { } -void +bool objc_start_method_definition (tree ARG_UNUSED (signature)) { + return true; } void @@ -248,6 +249,12 @@ objc_get_class_reference (tree ARG_UNUSED (name)) } tree +objc_get_interface_ivars (tree ARG_UNUSED (fieldlist)) +{ + return 0; +} + +tree objc_get_protocol_qualified_type (tree ARG_UNUSED (name), tree ARG_UNUSED (protos)) { diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 666f4188f98..b1e6eb2ee08 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -6597,9 +6597,19 @@ c_parser_objc_method_definition (c_parser *parser) return; } parser->objc_pq_context = false; - objc_start_method_definition (decl); - add_stmt (c_parser_compound_statement (parser)); - objc_finish_method_definition (current_function_decl); + if (objc_start_method_definition (decl)) + { + add_stmt (c_parser_compound_statement (parser)); + objc_finish_method_definition (current_function_decl); + } + else + { + /* This code is executed when we find a method definition + outside of an @implementation context. Parse the method (to + keep going) but do not emit any code. + */ + c_parser_compound_statement (parser); + } } /* Parse an objc-methodprotolist. diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 7ac866abfeb..065e9b802c7 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2897,8 +2897,13 @@ convert_arguments (tree typelist, VEC(tree,gc) *values, if (type == void_type_node) { - error_at (input_location, - "too many arguments to function %qE", function); + if (selector) + error_at (input_location, + "too many arguments to method %qE", selector); + else + error_at (input_location, + "too many arguments to function %qE", function); + if (fundecl && !DECL_BUILT_IN (fundecl)) inform (DECL_SOURCE_LOCATION (fundecl), "declared here"); return parmnum; diff --git a/gcc/calls.c b/gcc/calls.c index 388883137be..9a4768a32bd 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -610,6 +610,8 @@ flags_from_decl_or_type (const_tree exp) if (DECL_IS_NOVOPS (exp)) flags |= ECF_NOVOPS; + if (lookup_attribute ("leaf", DECL_ATTRIBUTES (exp))) + flags |= ECF_LEAF; if (TREE_NOTHROW (exp)) flags |= ECF_NOTHROW; diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 9ded1e6215b..9f3e68ee082 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -66,6 +66,10 @@ static bool first_pass; /* Set to true if crossjumps occured in the latest run of try_optimize_cfg. */ static bool crossjumps_occured; +/* Set to true if we couldn't run an optimization due to stale liveness + information; we should run df_analyze to enable more opportunities. */ +static bool block_was_dirty; + static bool try_crossjump_to_edge (int, edge, edge); static bool try_crossjump_bb (int, basic_block); static bool outgoing_edges_match (int, basic_block, basic_block); @@ -432,7 +436,7 @@ try_forward_edges (int mode, basic_block b) int counter, goto_locus; bool threaded = false; int nthreaded_edges = 0; - bool may_thread = first_pass | df_get_bb_dirty (b); + bool may_thread = first_pass || (b->flags & BB_MODIFIED) != 0; /* Skip complex edges because we don't know how to update them. @@ -467,7 +471,7 @@ try_forward_edges (int mode, basic_block b) { basic_block new_target = NULL; bool new_target_threaded = false; - may_thread |= df_get_bb_dirty (target); + may_thread |= (target->flags & BB_MODIFIED) != 0; if (FORWARDER_BLOCK_P (target) && !(single_succ_edge (target)->flags & EDGE_CROSSING) @@ -1180,7 +1184,6 @@ flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1, while (true) { - /* Ignore notes. */ while (!NONDEBUG_INSN_P (i1) && i1 != BB_END (bb1)) i1 = NEXT_INSN (i1); @@ -1188,6 +1191,10 @@ flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1, while (!NONDEBUG_INSN_P (i2) && i2 != BB_END (bb2)) i2 = NEXT_INSN (i2); + if ((i1 == BB_END (bb1) && !NONDEBUG_INSN_P (i1)) + || (i2 == BB_END (bb2) && !NONDEBUG_INSN_P (i2))) + break; + if (NOTE_P (i1) || NOTE_P (i2) || JUMP_P (i1) || JUMP_P (i2)) break; @@ -1857,8 +1864,8 @@ try_crossjump_bb (int mode, basic_block bb) /* If nothing changed since the last attempt, there is nothing we can do. */ if (!first_pass - && (!(df_get_bb_dirty (e->src)) - && !(df_get_bb_dirty (fallthru->src)))) + && !((e->src->flags & BB_MODIFIED) + || (fallthru->src->flags & BB_MODIFIED))) continue; if (try_crossjump_to_edge (mode, e, fallthru)) @@ -1907,8 +1914,8 @@ try_crossjump_bb (int mode, basic_block bb) /* If nothing changed since the last attempt, there is nothing we can do. */ if (!first_pass - && (!(df_get_bb_dirty (e->src)) - && !(df_get_bb_dirty (e2->src)))) + && !((e->src->flags & BB_MODIFIED) + || (e2->src->flags & BB_MODIFIED))) continue; if (try_crossjump_to_edge (mode, e, e2)) @@ -1927,6 +1934,265 @@ try_crossjump_bb (int mode, basic_block bb) return changed; } +/* Search the successors of BB for common insn sequences. When found, + share code between them by moving it across the basic block + boundary. Return true if any changes made. */ + +static bool +try_head_merge_bb (basic_block bb) +{ + basic_block final_dest_bb = NULL; + int max_match = INT_MAX; + edge e0; + rtx *headptr, *currptr; + bool changed, moveall; + unsigned ix; + rtx e0_last_head, cond, move_before; + unsigned nedges = EDGE_COUNT (bb->succs); + rtx jump = BB_END (bb); + regset live, live_union; + + /* Nothing to do if there is not at least two outgoing edges. */ + if (nedges < 2) + return false; + + /* Don't crossjump if this block ends in a computed jump, + unless we are optimizing for size. */ + if (optimize_bb_for_size_p (bb) + && bb != EXIT_BLOCK_PTR + && computed_jump_p (BB_END (bb))) + return false; + + cond = get_condition (jump, &move_before, true, false); + if (cond == NULL_RTX) + move_before = jump; + + for (ix = 0; ix < nedges; ix++) + if (EDGE_SUCC (bb, ix)->dest == EXIT_BLOCK_PTR) + return false; + + for (ix = 0; ix < nedges; ix++) + { + edge e = EDGE_SUCC (bb, ix); + basic_block other_bb = e->dest; + + if (df_get_bb_dirty (other_bb)) + { + block_was_dirty = true; + return false; + } + + if (e->flags & EDGE_ABNORMAL) + return false; + + /* Normally, all destination blocks must only be reachable from this + block, i.e. they must have one incoming edge. + + There is one special case we can handle, that of multiple consecutive + jumps where the first jumps to one of the targets of the second jump. + This happens frequently in switch statements for default labels. + The structure is as follows: + FINAL_DEST_BB + .... + if (cond) jump A; + fall through + BB + jump with targets A, B, C, D... + A + has two incoming edges, from FINAL_DEST_BB and BB + + In this case, we can try to move the insns through BB and into + FINAL_DEST_BB. */ + if (EDGE_COUNT (other_bb->preds) != 1) + { + edge incoming_edge, incoming_bb_other_edge; + edge_iterator ei; + + if (final_dest_bb != NULL + || EDGE_COUNT (other_bb->preds) != 2) + return false; + + /* We must be able to move the insns across the whole block. */ + move_before = BB_HEAD (bb); + while (!NONDEBUG_INSN_P (move_before)) + move_before = NEXT_INSN (move_before); + + if (EDGE_COUNT (bb->preds) != 1) + return false; + incoming_edge = EDGE_PRED (bb, 0); + final_dest_bb = incoming_edge->src; + if (EDGE_COUNT (final_dest_bb->succs) != 2) + return false; + FOR_EACH_EDGE (incoming_bb_other_edge, ei, final_dest_bb->succs) + if (incoming_bb_other_edge != incoming_edge) + break; + if (incoming_bb_other_edge->dest != other_bb) + return false; + } + } + + e0 = EDGE_SUCC (bb, 0); + e0_last_head = NULL_RTX; + changed = false; + + for (ix = 1; ix < nedges; ix++) + { + edge e = EDGE_SUCC (bb, ix); + rtx e0_last, e_last; + int nmatch; + + nmatch = flow_find_head_matching_sequence (e0->dest, e->dest, + &e0_last, &e_last, 0); + if (nmatch == 0) + return false; + + if (nmatch < max_match) + { + max_match = nmatch; + e0_last_head = e0_last; + } + } + + /* If we matched an entire block, we probably have to avoid moving the + last insn. */ + if (max_match > 0 + && e0_last_head == BB_END (e0->dest) + && (find_reg_note (e0_last_head, REG_EH_REGION, 0) + || control_flow_insn_p (e0_last_head))) + { + max_match--; + if (max_match == 0) + return false; + do + e0_last_head = prev_real_insn (e0_last_head); + while (DEBUG_INSN_P (e0_last_head)); + } + + if (max_match == 0) + return false; + + /* We must find a union of the live registers at each of the end points. */ + live = BITMAP_ALLOC (NULL); + live_union = BITMAP_ALLOC (NULL); + + currptr = XNEWVEC (rtx, nedges); + headptr = XNEWVEC (rtx, nedges); + + for (ix = 0; ix < nedges; ix++) + { + int j; + basic_block merge_bb = EDGE_SUCC (bb, ix)->dest; + rtx head = BB_HEAD (merge_bb); + + while (!NONDEBUG_INSN_P (head)) + head = NEXT_INSN (head); + headptr[ix] = head; + currptr[ix] = head; + + /* Compute the end point and live information */ + for (j = 1; j < max_match; j++) + do + head = NEXT_INSN (head); + while (!NONDEBUG_INSN_P (head)); + simulate_backwards_to_point (merge_bb, live, head); + IOR_REG_SET (live_union, live); + } + + /* If we're moving across two blocks, verify the validity of the + first move, then adjust the target and let the loop below deal + with the final move. */ + if (final_dest_bb != NULL) + { + rtx move_upto; + + moveall = can_move_insns_across (currptr[0], e0_last_head, move_before, + jump, e0->dest, live_union, + NULL, &move_upto); + if (!moveall) + e0_last_head = move_upto; + if (e0_last_head == NULL_RTX) + goto out; + + jump = BB_END (final_dest_bb); + cond = get_condition (jump, &move_before, true, false); + if (cond == NULL_RTX) + move_before = jump; + } + + do + { + rtx move_upto; + moveall = can_move_insns_across (currptr[0], e0_last_head, + move_before, jump, e0->dest, live_union, + NULL, &move_upto); + if (!moveall && move_upto == NULL_RTX) + { + if (jump == move_before) + break; + + /* Try again, using a different insertion point. */ + move_before = jump; + continue; + } + + if (final_dest_bb && !moveall) + /* We haven't checked whether a partial move would be OK for the first + move, so we have to fail this case. */ + break; + + changed = true; + for (;;) + { + if (currptr[0] == move_upto) + break; + for (ix = 0; ix < nedges; ix++) + { + rtx curr = currptr[ix]; + do + curr = NEXT_INSN (curr); + while (!NONDEBUG_INSN_P (curr)); + currptr[ix] = curr; + } + } + + reorder_insns (headptr[0], currptr[0], PREV_INSN (move_before)); + df_set_bb_dirty (EDGE_SUCC (bb, 0)->dest); + if (final_dest_bb != NULL) + df_set_bb_dirty (final_dest_bb); + df_set_bb_dirty (bb); + for (ix = 1; ix < nedges; ix++) + { + df_set_bb_dirty (EDGE_SUCC (bb, ix)->dest); + delete_insn_chain (headptr[ix], currptr[ix], false); + } + if (!moveall) + { + if (jump == move_before) + break; + + /* Try again, using a different insertion point. */ + move_before = jump; + for (ix = 0; ix < nedges; ix++) + { + rtx curr = currptr[ix]; + do + curr = NEXT_INSN (curr); + while (!NONDEBUG_INSN_P (curr)); + currptr[ix] = headptr[ix] = curr; + } + } + } + while (!moveall); + + out: + free (currptr); + free (headptr); + + crossjumps_occured |= changed; + + return changed; +} + /* Return true if BB contains just bb note, or bb note followed by only DEBUG_INSNs. */ @@ -1972,6 +2238,7 @@ try_optimize_cfg (int mode) one predecessor, they may be combined. */ do { + block_was_dirty = false; changed = false; iterations++; @@ -2170,6 +2437,13 @@ try_optimize_cfg (int mode) && try_crossjump_bb (mode, b)) changed_here = true; + if ((mode & CLEANUP_CROSSJUMP) + /* This can lengthen register lifetimes. Do it only after + reload. */ + && reload_completed + && try_head_merge_bb (b)) + changed_here = true; + /* Don't get confused by the index shift caused by deleting blocks. */ if (!changed_here) @@ -2182,6 +2456,13 @@ try_optimize_cfg (int mode) && try_crossjump_bb (mode, EXIT_BLOCK_PTR)) changed = true; + if (block_was_dirty) + { + /* This should only be set by head-merging. */ + gcc_assert (mode & CLEANUP_CROSSJUMP); + df_analyze (); + } + #ifdef ENABLE_CHECKING if (changed) verify_flow_info (); @@ -2366,8 +2647,7 @@ cleanup_cfg (int mode) if ((mode & CLEANUP_EXPENSIVE) && !reload_completed && !delete_trivially_dead_insns (get_insns (), max_reg_num ())) break; - else if ((mode & CLEANUP_CROSSJUMP) - && crossjumps_occured) + if ((mode & CLEANUP_CROSSJUMP) && crossjumps_occured) run_fast_dce (); } else diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 42372769049..f9d3fa6087e 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -205,19 +205,11 @@ static bool has_protected_decls; smaller than our cutoff threshold. Used for -Wstack-protector. */ static bool has_short_buffer; -/* Discover the byte alignment to use for DECL. Ignore alignment - we can't do with expected alignment of the stack boundary. */ +/* Update stack alignment requirement. */ -static unsigned int -get_decl_align_unit (tree decl) +static void +update_stack_alignment (unsigned int align) { - unsigned int align; - - align = LOCAL_DECL_ALIGNMENT (decl); - - if (align > MAX_SUPPORTED_STACK_ALIGNMENT) - align = MAX_SUPPORTED_STACK_ALIGNMENT; - if (SUPPORTS_STACK_ALIGNMENT) { if (crtl->stack_alignment_estimated < align) @@ -233,6 +225,22 @@ get_decl_align_unit (tree decl) crtl->stack_alignment_needed = align; if (crtl->max_used_stack_slot_alignment < align) crtl->max_used_stack_slot_alignment = align; +} + +/* Discover the byte alignment to use for DECL. Ignore alignment + we can't do with expected alignment of the stack boundary. */ + +static unsigned int +get_decl_align_unit (tree decl) +{ + unsigned int align; + + align = LOCAL_DECL_ALIGNMENT (decl); + + if (align > MAX_SUPPORTED_STACK_ALIGNMENT) + align = MAX_SUPPORTED_STACK_ALIGNMENT; + + update_stack_alignment (align); return align / BITS_PER_UNIT; } @@ -730,8 +738,7 @@ expand_one_stack_var_at (tree decl, HOST_WIDE_INT offset) offset -= frame_phase; align = offset & -offset; align *= BITS_PER_UNIT; - max_align = MAX (crtl->max_used_stack_slot_alignment, - PREFERRED_STACK_BOUNDARY); + max_align = crtl->max_used_stack_slot_alignment; if (align == 0 || align > max_align) align = max_align; diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 3138281b589..f7ce55841b7 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -421,7 +421,10 @@ rest_of_pass_free_cfg (void) /* The resource.c machinery uses DF but the CFG isn't guaranteed to be valid at that point so it would be too late to call df_analyze. */ if (optimize > 0 && flag_delayed_branch) - df_analyze (); + { + df_note_add_problem (); + df_analyze (); + } #endif free_bb_for_insn (); diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 470fb5a78fb..7293b6dee03 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -555,24 +555,29 @@ cgraph_same_body_alias_1 (tree alias, tree decl) return alias_node; } -/* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. +/* Attempt to mark ALIAS as an alias to DECL. Return alias node if successful + and NULL otherwise. Same body aliases are output whenever the body of DECL is output, and cgraph_node (ALIAS) transparently returns cgraph_node (DECL). */ -bool +struct cgraph_node * cgraph_same_body_alias (tree alias, tree decl) { #ifndef ASM_OUTPUT_DEF /* If aliases aren't supported by the assembler, fail. */ - return false; + return NULL; #endif /*gcc_assert (!assembler_name_hash);*/ - return cgraph_same_body_alias_1 (alias, decl) != NULL; + return cgraph_same_body_alias_1 (alias, decl); } -void +/* Add thunk alias into callgraph. The alias declaration is ALIAS and it + alises DECL with an adjustments made into the first parameter. + See comments in thunk_adjust for detail on the parameters. */ + +struct cgraph_node * cgraph_add_thunk (tree alias, tree decl, bool this_adjusting, HOST_WIDE_INT fixed_offset, HOST_WIDE_INT virtual_value, tree virtual_offset, @@ -599,13 +604,14 @@ cgraph_add_thunk (tree alias, tree decl, bool this_adjusting, node->thunk.virtual_offset_p = virtual_offset != NULL; node->thunk.alias = real_alias; node->thunk.thunk_p = true; + return node; } /* Returns the cgraph node assigned to DECL or NULL if no cgraph node is assigned. */ struct cgraph_node * -cgraph_get_node_or_alias (tree decl) +cgraph_get_node_or_alias (const_tree decl) { struct cgraph_node key, *node = NULL, **slot; @@ -614,7 +620,7 @@ cgraph_get_node_or_alias (tree decl) if (!cgraph_hash) return NULL; - key.decl = decl; + key.decl = CONST_CAST2 (tree, const_tree, decl); slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, NO_INSERT); @@ -628,7 +634,7 @@ cgraph_get_node_or_alias (tree decl) is assigned. */ struct cgraph_node * -cgraph_get_node (tree decl) +cgraph_get_node (const_tree decl) { struct cgraph_node key, *node = NULL, **slot; @@ -637,7 +643,7 @@ cgraph_get_node (tree decl) if (!cgraph_hash) return NULL; - key.decl = decl; + key.decl = CONST_CAST2 (tree, const_tree, decl); slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, NO_INSERT); @@ -1849,8 +1855,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) fprintf (f, " local"); if (node->local.externally_visible) fprintf (f, " externally_visible"); - if (node->local.used_from_object_file) - fprintf (f, " used_from_object_file"); if (node->local.finalized) fprintf (f, " finalized"); if (node->local.disregard_inline_limits) @@ -2124,7 +2128,6 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq, new_node->analyzed = n->analyzed; new_node->local = n->local; new_node->local.externally_visible = false; - new_node->local.used_from_object_file = false; new_node->local.local = true; new_node->local.vtable_method = false; new_node->global = n->global; @@ -2318,7 +2321,6 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, else new_node->clone.combined_args_to_skip = args_to_skip; new_node->local.externally_visible = 0; - new_node->local.used_from_object_file = 0; new_node->local.local = 1; new_node->lowered = true; new_node->reachable = true; @@ -2369,7 +2371,7 @@ cgraph_function_body_availability (struct cgraph_node *node) AVAIL_AVAILABLE here? That would be good reason to preserve this bit. */ - else if (DECL_REPLACEABLE_P (node->decl) && !DECL_EXTERNAL (node->decl)) + else if (decl_replaceable_p (node->decl) && !DECL_EXTERNAL (node->decl)) avail = AVAIL_OVERWRITABLE; else avail = AVAIL_AVAILABLE; @@ -2556,6 +2558,7 @@ cgraph_make_node_local (struct cgraph_node *node) node->local.externally_visible = false; node->local.local = true; + node->resolution = LDPR_PREVAILING_DEF_IRONLY; gcc_assert (cgraph_function_body_availability (node) == AVAIL_LOCAL); } } @@ -2720,7 +2723,8 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node) return false; /* Only COMDAT functions can be removed if externally visible. */ if (node->local.externally_visible - && (!DECL_COMDAT (node->decl) || node->local.used_from_object_file)) + && (!DECL_COMDAT (node->decl) + || cgraph_used_from_object_file_p (node))) return false; /* Constructors and destructors are executed by the runtime, however we can get rid of all pure constructors and destructors. */ @@ -2753,7 +2757,7 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node) bool cgraph_will_be_removed_from_program_if_no_direct_calls (struct cgraph_node *node) { - if (node->local.used_from_object_file) + if (cgraph_used_from_object_file_p (node)) return false; if (!in_lto_p && !flag_whole_program) return cgraph_only_called_directly_p (node); @@ -2761,4 +2765,35 @@ cgraph_will_be_removed_from_program_if_no_direct_calls (struct cgraph_node *node return cgraph_can_remove_if_no_direct_calls_p (node); } +/* Return true when RESOLUTION indicate that linker will use + the symbol from non-LTo object files. */ + +bool +resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution) +{ + return (resolution == LDPR_PREVAILING_DEF + || resolution == LDPR_PREEMPTED_REG + || resolution == LDPR_RESOLVED_EXEC + || resolution == LDPR_RESOLVED_DYN); +} + +/* Return true when NODE is known to be used from other (non-LTO) object file. + Known only when doing LTO via linker plugin. */ + +bool +cgraph_used_from_object_file_p (struct cgraph_node *node) +{ + struct cgraph_node *alias; + + if (!TREE_PUBLIC (node->decl)) + return false; + if (resolution_used_from_other_file_p (node->resolution)) + return true; + for (alias = node->same_body; alias; alias = alias->next) + if (TREE_PUBLIC (alias->decl) + && resolution_used_from_other_file_p (alias->resolution)) + return true; + return false; +} + #include "gt-cgraph.h" diff --git a/gcc/cgraph.h b/gcc/cgraph.h index c868d329542..330c8839636 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_CGRAPH_H #define GCC_CGRAPH_H +#include "plugin-api.h" #include "vec.h" #include "tree.h" #include "basic-block.h" @@ -101,9 +102,6 @@ struct GTY(()) cgraph_local_info { /* Set when function is visible by other units. */ unsigned externally_visible : 1; - - /* Set when resolver determines that function is visible by other units. */ - unsigned used_from_object_file : 1; /* Set once it has been finalized so we consider it to be output. */ unsigned finalized : 1; @@ -259,6 +257,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node { /* unique id for profiling. pid is not suitable because of different number of cfg nodes with -fprofile-generate and -fprofile-use */ int pid; + enum ld_plugin_symbol_resolution resolution; /* Set when function must be output for some reason. The primary use of this flag is to mark functions needed to be output for @@ -476,6 +475,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node { PTR GTY ((skip)) aux; /* Ordering of all cgraph nodes. */ int order; + enum ld_plugin_symbol_resolution resolution; /* Set when function must be output - it is externally visible or its address is taken. */ @@ -492,8 +492,6 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node { unsigned output : 1; /* Set when function is visible by other units. */ unsigned externally_visible : 1; - /* Set when resolver determines that variable is visible by other units. */ - unsigned used_from_object_file : 1; /* Set for aliases once they got through assemble_alias. Also set for extra name aliases in varpool_extra_name_alias. */ unsigned alias : 1; @@ -503,8 +501,6 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node { During WPA output it is used to mark nodes that are present in multiple partitions. */ unsigned in_other_partition : 1; - /* True when variable is constant and its value is known. */ - unsigned int const_value_known : 1; }; /* Every top level asm statement is put into a cgraph_asm_node. */ @@ -561,11 +557,12 @@ struct cgraph_edge *cgraph_create_edge (struct cgraph_node *, gimple, gcov_type, int, int); struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple, int, gcov_type, int, int); -struct cgraph_node * cgraph_get_node (tree); -struct cgraph_node * cgraph_get_node_or_alias (tree); -struct cgraph_node *cgraph_node (tree); -bool cgraph_same_body_alias (tree, tree); -void cgraph_add_thunk (tree, tree, bool, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree); +struct cgraph_node * cgraph_get_node (const_tree); +struct cgraph_node * cgraph_get_node_or_alias (const_tree); +struct cgraph_node * cgraph_node (tree); +struct cgraph_node * cgraph_same_body_alias (tree, tree); +struct cgraph_node * cgraph_add_thunk (tree, tree, bool, HOST_WIDE_INT, + HOST_WIDE_INT, tree, tree); void cgraph_remove_same_body_alias (struct cgraph_node *); struct cgraph_node *cgraph_node_for_asm (tree); struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple); @@ -614,6 +611,9 @@ bool cgraph_will_be_removed_from_program_if_no_direct_calls (struct cgraph_node *node); bool cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node); +bool resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution); +bool cgraph_used_from_object_file_p (struct cgraph_node *node); +bool varpool_used_from_object_file_p (struct varpool_node *node); /* In cgraphunit.c */ extern FILE *cgraph_dump_file; @@ -718,17 +718,17 @@ void cgraph_make_node_local (struct cgraph_node *); bool cgraph_node_can_be_local_p (struct cgraph_node *); -struct varpool_node * varpool_get_node (tree decl); +struct varpool_node * varpool_get_node (const_tree decl); void varpool_remove_node (struct varpool_node *node); bool varpool_assemble_pending_decls (void); bool varpool_assemble_decl (struct varpool_node *node); bool varpool_analyze_pending_decls (void); void varpool_remove_unreferenced_decls (void); void varpool_empty_needed_queue (void); -bool varpool_extra_name_alias (tree, tree); +struct varpool_node * varpool_extra_name_alias (tree, tree); const char * varpool_node_name (struct varpool_node *node); void varpool_reset_queue (void); -bool varpool_decide_const_value_known (struct varpool_node *node); +bool const_value_known_p (tree); /* Walk all reachable static variables. */ #define FOR_EACH_STATIC_VARIABLE(node) \ diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 024a3bc2eed..b51a71c2b72 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -363,7 +363,13 @@ cgraph_finalize_function (tree decl, bool nested) there. */ if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) || DECL_STATIC_CONSTRUCTOR (decl) - || DECL_STATIC_DESTRUCTOR (decl)) + || DECL_STATIC_DESTRUCTOR (decl) + /* COMDAT virtual functions may be referenced by vtable from + other compilatoin unit. Still we want to devirtualize calls + to those so we need to analyze them. + FIXME: We should introduce may edges for this purpose and update + their handling in unreachable function removal and inliner too. */ + || (DECL_VIRTUAL_P (decl) && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl)))) cgraph_mark_reachable_node (node); /* If we've not yet emitted decl, tell the debug info about it. */ @@ -861,6 +867,7 @@ cgraph_analyze_functions (void) static struct varpool_node *first_analyzed_var; struct cgraph_node *node, *next; + bitmap_obstack_initialize (NULL); process_function_and_variable_attributes (first_processed, first_analyzed_var); first_processed = cgraph_nodes; @@ -971,6 +978,7 @@ cgraph_analyze_functions (void) fprintf (cgraph_dump_file, "\n\nReclaimed "); dump_cgraph (cgraph_dump_file); } + bitmap_obstack_release (NULL); first_analyzed = cgraph_nodes; ggc_collect (); } @@ -2151,6 +2159,7 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) new_stmt = gimple_call_copy_skip_args (e->call_stmt, e->callee->clone.combined_args_to_skip); + gimple_call_set_fndecl (new_stmt, e->callee->decl); if (gimple_vdef (new_stmt) && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME) @@ -2160,10 +2169,11 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) gsi_replace (&gsi, new_stmt, true); } else - new_stmt = e->call_stmt; - - gimple_call_set_fndecl (new_stmt, e->callee->decl); - update_stmt (new_stmt); + { + new_stmt = e->call_stmt; + gimple_call_set_fndecl (new_stmt, e->callee->decl); + update_stmt (new_stmt); + } cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt); diff --git a/gcc/combine.c b/gcc/combine.c index 618e07df4f0..6131b413d1d 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -3690,36 +3690,41 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p) && GET_CODE (XVECEXP (newpat, 0, 1)) == SET && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != ZERO_EXTRACT && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != STRICT_LOW_PART - && ! use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)), - DF_INSN_LUID (i2)) && ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 1)), XVECEXP (newpat, 0, 0)) && ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 0)), XVECEXP (newpat, 0, 1)) && ! (contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 0))) - && contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 1)))) -#ifdef HAVE_cc0 - /* We cannot split the parallel into two sets if both sets - reference cc0. */ - && ! (reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0)) - && reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 1))) -#endif - ) + && contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 1))))) { /* Normally, it doesn't matter which of the two is done first, - but it does if one references cc0. In that case, it has to + but the one that references cc0 can't be the second, and + one which uses any regs/memory set in between i2 and i3 can't be first. */ + if (!use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)), + DF_INSN_LUID (i2)) +#ifdef HAVE_cc0 + && !reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0)) +#endif + ) + { + newi2pat = XVECEXP (newpat, 0, 1); + newpat = XVECEXP (newpat, 0, 0); + } + else if (!use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 0)), + DF_INSN_LUID (i2)) #ifdef HAVE_cc0 - if (reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0))) + && !reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 1)) +#endif + ) { newi2pat = XVECEXP (newpat, 0, 0); newpat = XVECEXP (newpat, 0, 1); } else -#endif { - newi2pat = XVECEXP (newpat, 0, 1); - newpat = XVECEXP (newpat, 0, 0); + undo_all (); + return 0; } i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); @@ -3735,44 +3740,11 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx i0, int *new_direct_jump_p) { rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0); if (reg_overlap_mentioned_p (reg, newpat)) - break; + { + undo_all (); + return 0; + } } - - if (i >= 0) - { - /* CLOBBERs on newi2pat prevent it going first. - Try the other order of the insns if possible. */ - temp = newpat; - newpat = XVECEXP (newi2pat, 0, 0); - newi2pat = temp; -#ifdef HAVE_cc0 - if (reg_referenced_p (cc0_rtx, newpat)) - { - undo_all (); - return 0; - } -#endif - - i2_code_number = recog_for_combine (&newi2pat, i2, - &new_i2_notes); - if (i2_code_number < 0) - { - undo_all (); - return 0; - } - - if (GET_CODE (newi2pat) == PARALLEL) - for (i = XVECLEN (newi2pat, 0) - 1; i >= 0; i--) - if (GET_CODE (XVECEXP (newi2pat, 0, i)) == CLOBBER) - { - rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0); - if (reg_overlap_mentioned_p (reg, newpat)) - { - undo_all (); - return 0; - } - } - } } insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); diff --git a/gcc/common.opt b/gcc/common.opt index 3c273320d23..1cbbf5a60fe 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -23,40 +23,214 @@ ; Please try to keep this file in ASCII collating order. +Variable +int target_flags + ### Driver +-assemble +Driver Alias(S) + +-compile +Driver Alias(c) + +-coverage +Driver Alias(coverage) + +-debug +Common Alias(g) + +-dump +Common Separate Alias(d) + +-dump= +Common Joined Alias(d) + +-dumpbase +Common Separate Alias(dumpbase) + +-dumpdir +Common Separate Alias(dumpdir) + +-entry +Driver Separate Alias(e) + +-entry= +Driver Joined Alias(e) + +-extra-warnings +Common Warning Alias(Wextra) + +-for-assembler +Driver Separate Alias(Xassembler) + +-for-assembler= +Driver JoinedOrMissing Alias(Xassembler) + +-for-linker +Driver Separate Alias(Xlinker) + +-for-linker= +Driver JoinedOrMissing Alias(Xlinker) + +-force-link +Driver Separate Alias(u) + +-force-link= +Driver Joined Alias(u) + -help -Common Driver +Common Driver Var(help_flag) Display this information -help= Common Driver Report Joined --help=<class> Display descriptions of a specific class of options. <class> is one or more of optimizers, target, warnings, undocumented, params +-language +Driver Separate Alias(x) + +-language= +Driver Joined Alias(x) + +-library-directory +Driver Separate Alias(L) + +-library-directory= +Driver Joined Alias(L) + +-no-canonical-prefixes +Driver Alias(no-canonical-prefixes) + +-no-standard-libraries +Driver Alias(nostdlib) + +-no-warnings +Common Alias(w) + +-optimize +Common Alias(O) + +-output +Common Driver Separate Alias(o) MissingArgError(missing filename after %qs) + +-output= +Common Driver Joined Alias(o) MissingArgError(missing filename after %qs) + +-pass-exit-codes +Driver Alias(pass-exit-codes) + +-pedantic +Common Alias(pedantic) + +-pedantic-errors +Common Alias(pedantic-errors) + +-pie +Common Alias(pie) + +-pipe +Driver Alias(pipe) + +-prefix +Driver Separate Alias(B) + +-prefix= +Driver JoinedOrMissing Alias(B) + +-preprocess +Driver Alias(E) + +-print-file-name +Driver Separate Alias(print-file-name=) + +-print-file-name= +Driver JoinedOrMissing Alias(print-file-name=) + +-print-libgcc-file-name +Driver Alias(print-libgcc-file-name) + +-print-multi-directory +Driver Alias(print-multi-directory) + +-print-multi-lib +Driver Alias(print-multi-lib) + +-print-multi-os-directory +Driver Alias(print-multi-os-directory) + +-print-prog-name +Driver Separate Alias(print-prog-name=) + +-print-prog-name= +Driver JoinedOrMissing Alias(print-prog-name=) + +-print-search-dirs +Driver Alias(print-search-dirs) + +-print-sysroot +Driver Alias(print-sysroot) + +-print-sysroot-headers-suffix +Driver Alias(print-sysroot-headers-suffix) + +-profile +Common Alias(p) + +-save-temps +Driver Alias(save-temps) + +-shared +Common Alias(shared) + +-specs +Driver Separate Alias(specs=) + +-specs= +Driver Joined Alias(specs=) + +-static +Driver Alias(static) + +-symbolic +Driver Alias(symbolic) + -target-help Common Driver Alias for --help=target -;; The following four entries are to work around the gcc driver -;; program's insatiable desire to turn options starting with a -;; double dash (--) into options starting with a dash f (-f). +-time +Driver Alias(time) + +-verbose +Driver Alias(v) + +;; The driver used to convert options such as --help into forms such +;; as -fhelp; the following four entries are for compatibility with +;; any direct uses of those (undocumented) -f forms fhelp -Common Driver Var(help_flag) +Common Driver Alias(-help) fhelp= -Common Driver Joined +Common Driver Joined Alias(-help=) ftarget-help -Common Driver +Common Driver Alias(-target-help) fversion -Common Driver +Common Driver Alias(-version) -param Common Separate --param <param>=<value> Set parameter <param> to value. See below for a complete list of parameters +-param= +Common Joined Alias(-param) + +-sysroot +Driver Separate Alias(-sysroot=) + -sysroot= Driver JoinedOrMissing @@ -309,8 +483,8 @@ Common Separate RejectDriver auxbase-strip Common Separate RejectDriver -combine -Driver Var(combine_flag) +coverage +Driver c Driver @@ -336,6 +510,9 @@ Driver dumpversion Driver +e +Driver Joined Separate + ; The version of the C++ ABI in use. The following values are allowed: ; ; 0: The version of the ABI believed most conformant with the C++ ABI @@ -653,11 +830,11 @@ Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps fdump-unnumbered -Common Report Var(flag_dump_unnumbered) VarExists +Common Report Var(flag_dump_unnumbered) Suppress output of instruction numbers, line number notes and addresses in debugging dumps fdump-unnumbered-links -Common Report Var(flag_dump_unnumbered_links) VarExists +Common Report Var(flag_dump_unnumbered_links) Suppress output of previous and next insn numbers in debugging dumps fdwarf2-cfi-asm @@ -1612,16 +1789,27 @@ Just generate unwind tables for exception handling fuse-linker-plugin Common Undocumented +; Positive if we should track variables, negative if we should run +; the var-tracking pass only to discard debug annotations, zero if +; we're not to run it. When flag_var_tracking == 2 (AUTODETECT_VALUE) it +; will be set according to optimize, debug_info_level and debug_hooks +; in process_options (). fvar-tracking -Common Report Var(flag_var_tracking) VarExists Optimization +Common Report Var(flag_var_tracking) Init(2) Optimization Perform variable tracking +; Positive if we should track variables at assignments, negative if +; we should run the var-tracking pass only to discard debug +; annotations. When flag_var_tracking_assignments == +; AUTODETECT_VALUE it will be set according to flag_var_tracking. fvar-tracking-assignments -Common Report Var(flag_var_tracking_assignments) VarExists Optimization +Common Report Var(flag_var_tracking_assignments) Init(2) Optimization Perform variable tracking by annotating assignments +; Nonzero if we should toggle flag_var_tracking_assignments after +; processing options and computing its default. */ fvar-tracking-assignments-toggle -Common Report Var(flag_var_tracking_assignments_toggle) VarExists Optimization +Common Report Var(flag_var_tracking_assignments_toggle) Optimization Toggle -fvar-tracking-assignments fvar-tracking-uninit @@ -1831,6 +2019,13 @@ Driver Var(report_times) time= Driver JoinedOrMissing +u +Driver Joined Separate + +undef +Driver +; C option, but driver must not handle as "-u ndef". + v Driver @@ -1874,6 +2069,9 @@ Driver static-libstdc++ Driver +symbolic +Driver + pie Common RejectNegative Negative(shared) Create a position independent executable diff --git a/gcc/config.gcc b/gcc/config.gcc index d5f075517da..c504249cefd 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -721,7 +721,7 @@ alpha*-dec-osf5.1*) alpha64-dec-*vms*) tm_file="${tm_file} alpha/vms.h alpha/vms64.h" xm_file="alpha/xm-vms.h vms/xm-vms64.h" - tmake_file="alpha/t-alpha vms/t-vms vms/t-vms64 alpha/t-vms alpha/t-ieee" + tmake_file="alpha/t-alpha vms/t-vms alpha/t-vms alpha/t-ieee" xmake_file=vms/x-vms exeext=.exe install_headers_dir=install-headers-cp @@ -1442,7 +1442,7 @@ i[34567]86-*-mingw* | x86_64-*-mingw*) else tmake_eh_file="i386/t-sjlj-eh" fi - tmake_file="${tmake_file} ${tmake_eh_file} i386/t-cygming i386/t-dfprules" + tmake_file="${tmake_file} ${tmake_eh_file} i386/t-cygming t-dfprules" case ${target} in x86_64-w64-*) tmake_file="${tmake_file} i386/t-mingw-w64" @@ -1549,7 +1549,7 @@ ia64*-*-hpux*) ia64-hp-*vms*) tm_file="${tm_file} elfos.h ia64/sysv4.h ia64/elf.h ia64/vms.h ia64/vms64.h" xm_file="vms/xm-vms.h vms/xm-vms64.h" - tmake_file="vms/t-vms vms/t-vms64 ia64/t-ia64 ia64/t-vms" + tmake_file="vms/t-vms ia64/t-ia64 ia64/t-vms" xmake_file=vms/x-vms target_cpu_default="0" if test x$gas = xyes diff --git a/gcc/config.in b/gcc/config.in index a03b65309dc..574c033e894 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -936,22 +936,13 @@ /* Define 0/1 if your assembler supports CFI directives. */ -#ifndef USED_FOR_TARGET #undef HAVE_GAS_CFI_DIRECTIVE -#endif - /* Define 0/1 if your assembler supports .cfi_personality. */ -#ifndef USED_FOR_TARGET #undef HAVE_GAS_CFI_PERSONALITY_DIRECTIVE -#endif - /* Define 0/1 if your assembler supports .cfi_sections. */ -#ifndef USED_FOR_TARGET #undef HAVE_GAS_CFI_SECTIONS_DIRECTIVE -#endif - /* Define if your assembler supports the .loc discriminator sub-directive. */ #ifndef USED_FOR_TARGET diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 4db554cbfbe..49c86fd9310 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -10029,6 +10029,7 @@ alpha_use_linkage (rtx func, tree cfundecl, int lflag, int rflag) al = ggc_alloc_alpha_links (); al->num = cfaf->num; + al->target = NULL; node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name); if (node) diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index f0d8b9dba4d..be885c1235d 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -916,7 +916,7 @@ extern int alpha_memory_latency; #define NONSTRICT_REG_OK_FP_BASE_P(X) \ (REGNO (X) == 31 || REGNO (X) == 63 \ || (REGNO (X) >= FIRST_PSEUDO_REGISTER \ - && REGNO (X) < LAST_VIRTUAL_REGISTER)) + && REGNO (X) < LAST_VIRTUAL_POINTER_REGISTER)) /* Nonzero if X is a hard reg that can be used as a base reg. */ #define STRICT_REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 59e1c5024ec..c861bb6a361 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -86,6 +86,8 @@ extern int arm_coproc_mem_operand (rtx, bool); extern int neon_vector_mem_operand (rtx, int); extern int neon_struct_mem_operand (rtx); extern int arm_no_early_store_addr_dep (rtx, rtx); +extern int arm_early_store_addr_dep (rtx, rtx); +extern int arm_early_load_addr_dep (rtx, rtx); extern int arm_no_early_alu_shift_dep (rtx, rtx); extern int arm_no_early_alu_shift_value_dep (rtx, rtx); extern int arm_no_early_mul_dep (rtx, rtx); @@ -127,6 +129,7 @@ extern const char *output_move_quad (rtx *); extern const char *output_move_vfp (rtx *operands); extern const char *output_move_neon (rtx *operands); extern int arm_attr_length_move_neon (rtx); +extern int arm_address_offset_is_imm (rtx); extern const char *output_add_immediate (rtx *); extern const char *arithmetic_instr (rtx, int); extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int); @@ -148,8 +151,6 @@ extern const char *arm_output_memory_barrier (rtx *); extern const char *arm_output_sync_insn (rtx, rtx *); extern unsigned int arm_sync_loop_insns (rtx , rtx *); -extern bool arm_output_addr_const_extra (FILE *, rtx); - #if defined TREE_CODE extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree); extern bool arm_pad_arg_upward (enum machine_mode, const_tree); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 206e06cac52..44cbc8e1353 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -224,6 +224,7 @@ static bool arm_cannot_copy_insn_p (rtx); static bool arm_tls_symbol_p (rtx x); static int arm_issue_rate (void); static void arm_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; +static bool arm_output_addr_const_extra (FILE *, rtx); static bool arm_allocate_stack_slots_for_args (void); static const char *arm_invalid_parameter_type (const_tree t); static const char *arm_invalid_return_type (const_tree t); @@ -239,6 +240,7 @@ static rtx arm_pic_static_addr (rtx orig, rtx reg); static bool cortex_a9_sched_adjust_cost (rtx, rtx, rtx, int *); static bool xscale_sched_adjust_cost (rtx, rtx, rtx, int *); static unsigned int arm_units_per_simd_word (enum machine_mode); +static bool arm_class_likely_spilled_p (reg_class_t); /* Table of machine attributes. */ @@ -308,6 +310,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P #define TARGET_PRINT_OPERAND_PUNCT_VALID_P arm_print_operand_punct_valid_p +#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA +#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA arm_output_addr_const_extra + #undef TARGET_ASM_FUNCTION_PROLOGUE #define TARGET_ASM_FUNCTION_PROLOGUE arm_output_function_prologue @@ -545,6 +550,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_CAN_ELIMINATE #define TARGET_CAN_ELIMINATE arm_can_eliminate +#undef TARGET_CLASS_LIKELY_SPILLED_P +#define TARGET_CLASS_LIKELY_SPILLED_P arm_class_likely_spilled_p + struct gcc_target targetm = TARGET_INITIALIZER; /* Obstack for minipool constant handling. */ @@ -5847,7 +5855,8 @@ thumb1_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p) && (REGNO (XEXP (x, 0)) == FRAME_POINTER_REGNUM || REGNO (XEXP (x, 0)) == ARG_POINTER_REGNUM || (REGNO (XEXP (x, 0)) >= FIRST_VIRTUAL_REGISTER - && REGNO (XEXP (x, 0)) <= LAST_VIRTUAL_REGISTER)) + && REGNO (XEXP (x, 0)) + <= LAST_VIRTUAL_POINTER_REGISTER)) && GET_MODE_SIZE (mode) >= 4 && GET_CODE (XEXP (x, 1)) == CONST_INT && (INTVAL (XEXP (x, 1)) & 3) == 0) @@ -13345,6 +13354,34 @@ arm_attr_length_move_neon (rtx insn) return 4; } +/* Return nonzero if the offset in the address is an immediate. Otherwise, + return zero. */ + +int +arm_address_offset_is_imm (rtx insn) +{ + rtx mem, addr; + + extract_insn_cached (insn); + + if (REG_P (recog_data.operand[0])) + return 0; + + mem = recog_data.operand[0]; + + gcc_assert (MEM_P (mem)); + + addr = XEXP (mem, 0); + + if (GET_CODE (addr) == REG + || (GET_CODE (addr) == PLUS + && GET_CODE (XEXP (addr, 0)) == REG + && GET_CODE (XEXP (addr, 1)) == CONST_INT)) + return 1; + else + return 0; +} + /* Output an ADD r, s, #n where n may be too big for one instruction. If adding zero to one register, output nothing. */ const char * @@ -21503,6 +21540,38 @@ arm_no_early_store_addr_dep (rtx producer, rtx consumer) return !reg_overlap_mentioned_p (value, addr); } +/* Return nonzero if the CONSUMER instruction (a store) does need + PRODUCER's value to calculate the address. */ + +int +arm_early_store_addr_dep (rtx producer, rtx consumer) +{ + return !arm_no_early_store_addr_dep (producer, consumer); +} + +/* Return nonzero if the CONSUMER instruction (a load) does need + PRODUCER's value to calculate the address. */ + +int +arm_early_load_addr_dep (rtx producer, rtx consumer) +{ + rtx value = PATTERN (producer); + rtx addr = PATTERN (consumer); + + if (GET_CODE (value) == COND_EXEC) + value = COND_EXEC_CODE (value); + if (GET_CODE (value) == PARALLEL) + value = XVECEXP (value, 0, 0); + value = XEXP (value, 0); + if (GET_CODE (addr) == COND_EXEC) + addr = COND_EXEC_CODE (addr); + if (GET_CODE (addr) == PARALLEL) + addr = XVECEXP (addr, 0, 0); + addr = XEXP (addr, 1); + + return reg_overlap_mentioned_p (value, addr); +} + /* Return nonzero if the CONSUMER instruction (an ALU op) does not have an early register shift value or amount dependency on the result of PRODUCER. */ @@ -21892,6 +21961,22 @@ arm_units_per_simd_word (enum machine_mode mode ATTRIBUTE_UNUSED) ? (TARGET_NEON_VECTORIZE_QUAD ? 16 : 8) : UNITS_PER_WORD); } +/* Implement TARGET_CLASS_LIKELY_SPILLED_P. + + We need to define this for LO_REGS on thumb. Otherwise we can end up + using r0-r4 for function arguments, r7 for the stack frame and don't + have enough left over to do doubleword arithmetic. */ + +static bool +arm_class_likely_spilled_p (reg_class_t rclass) +{ + if ((TARGET_THUMB && rclass == LO_REGS) + || rclass == CC_REG) + return true; + + return false; +} + /* Implements target hook small_register_classes_for_mode_p. */ bool arm_small_register_classes_for_mode_p (enum machine_mode mode ATTRIBUTE_UNUSED) @@ -22371,7 +22456,9 @@ arm_output_dwarf_dtprel (FILE *file, int size, rtx x) fputs ("(tlsldo)", file); } -bool +/* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */ + +static bool arm_output_addr_const_extra (FILE *fp, rtx x) { if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS) diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 8727305a6e2..9bd1c69e849 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1284,13 +1284,6 @@ enum reg_class || reg_classes_intersect_p (VFP_REGS, (CLASS)) \ : 0) -/* We need to define this for LO_REGS on thumb. Otherwise we can end up - using r0-r4 for function arguments, r7 for the stack frame and don't - have enough left over to do doubleword arithmetic. */ -#define CLASS_LIKELY_SPILLED_P(CLASS) \ - ((TARGET_THUMB && (CLASS) == LO_REGS) \ - || (CLASS) == CC_REG) - /* The class value for index registers, and the one for base regs. */ #define INDEX_REG_CLASS (TARGET_THUMB1 ? LO_REGS : GENERAL_REGS) #define BASE_REG_CLASS (TARGET_THUMB1 ? LO_REGS : CORE_REGS) @@ -2426,10 +2419,6 @@ extern int making_const_table; & ~ (unsigned HOST_WIDE_INT) 0xffffffff) \ : 0)))) -#define OUTPUT_ADDR_CONST_EXTRA(file, x, fail) \ - if (arm_output_addr_const_extra (file, x) == FALSE) \ - goto fail - /* A C expression whose value is RTL representing the value of the return address for the frame COUNT steps up from the current frame. */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 61b95e3ee00..c54bb2a1f37 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -497,16 +497,16 @@ ;; True if the generic scheduling description should be used. (define_attr "generic_sched" "yes,no" - (const (if_then_else - (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9") - (eq_attr "tune_cortexr4" "yes")) + (const (if_then_else + (ior (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs,cortexa5,cortexa8,cortexa9,cortexm4") + (eq_attr "tune_cortexr4" "yes")) (const_string "no") (const_string "yes")))) (define_attr "generic_vfp" "yes,no" (const (if_then_else (and (eq_attr "fpu" "vfp") - (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9") + (eq_attr "tune" "!arm1020e,arm1022e,cortexa5,cortexa8,cortexa9,cortexm4") (eq_attr "tune_cortexr4" "no")) (const_string "yes") (const_string "no")))) @@ -521,6 +521,8 @@ (include "cortex-a9.md") (include "cortex-r4.md") (include "cortex-r4f.md") +(include "cortex-m4.md") +(include "cortex-m4-fpu.md") (include "vfp11.md") @@ -4040,7 +4042,8 @@ (define_insn "zero_extend<mode>di2" [(set (match_operand:DI 0 "s_register_operand" "=r") - (zero_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))] + (zero_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>" + "<qhs_extenddi_cstr>")))] "TARGET_32BIT <qhs_zextenddi_cond>" "#" [(set_attr "length" "8") @@ -4050,7 +4053,8 @@ (define_insn "extend<mode>di2" [(set (match_operand:DI 0 "s_register_operand" "=r") - (sign_extend:DI (match_operand:QHSI 1 "nonimmediate_operand" "rm")))] + (sign_extend:DI (match_operand:QHSI 1 "<qhs_extenddi_op>" + "<qhs_extenddi_cstr>")))] "TARGET_32BIT <qhs_sextenddi_cond>" "#" [(set_attr "length" "8") @@ -5117,7 +5121,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=r") (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "general_operand" "i")))] - "TARGET_32BIT" + "arm_arch_thumb2" "movt%?\t%0, #:upper16:%c2" [(set_attr "predicable" "yes") (set_attr "length" "4")] @@ -10577,7 +10581,7 @@ (const_int 16) (const_int 16)) (match_operand:SI 1 "const_int_operand" ""))] - "TARGET_32BIT" + "arm_arch_thumb2" "movt%?\t%0, %c1" [(set_attr "predicable" "yes") (set_attr "length" "4")] diff --git a/gcc/config/arm/cortex-m4-fpu.md b/gcc/config/arm/cortex-m4-fpu.md new file mode 100644 index 00000000000..7de115c5209 --- /dev/null +++ b/gcc/config/arm/cortex-m4-fpu.md @@ -0,0 +1,111 @@ +;; ARM Cortex-M4 FPU pipeline description +;; Copyright (C) 2010 Free Software Foundation, Inc. +;; Contributed by CodeSourcery. +;; +;; 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 3, 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 COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +;; Use an artifial unit to model FPU. +(define_cpu_unit "cortex_m4_v" "cortex_m4") + +(define_reservation "cortex_m4_ex_v" "cortex_m4_ex+cortex_m4_v") + +;; Integer instructions following VDIV or VSQRT complete out-of-order. +(define_insn_reservation "cortex_m4_fdivs" 15 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fdivs")) + "cortex_m4_ex_v,cortex_m4_v*13") + +(define_insn_reservation "cortex_m4_vmov_1" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fcpys,fconsts")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_vmov_2" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_2_r,r_2_f")) + "cortex_m4_ex_v*2") + +(define_insn_reservation "cortex_m4_fmuls" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fmuls")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_fmacs" 4 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fmacs")) + "cortex_m4_ex_v*3") + +(define_insn_reservation "cortex_m4_ffariths" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "ffariths")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_fadds" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fadds")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_fcmps" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "fcmps")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_f_flag" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_flag")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_f_cvt" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_cvt")) + "cortex_m4_ex_v") + +(define_insn_reservation "cortex_m4_f_load" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_load")) + "cortex_m4_ex_v*2") + +(define_insn_reservation "cortex_m4_f_store" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_store")) + "cortex_m4_ex_v*2") + +(define_insn_reservation "cortex_m4_f_loadd" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_loadd")) + "cortex_m4_ex_v*3") + +(define_insn_reservation "cortex_m4_f_stored" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "f_stored")) + "cortex_m4_ex_v*3") + +;; MAC instructions consume their addend one cycle later. If the result +;; of an arithmetic instruction is consumed as the addend of the following +;; MAC instruction, the latency can be decreased by one. + +(define_bypass 1 "cortex_m4_fadds,cortex_m4_fmuls,cortex_m4_f_cvt" + "cortex_m4_fmacs" + "arm_no_early_mul_dep") + +(define_bypass 3 "cortex_m4_fmacs" + "cortex_m4_fmacs" + "arm_no_early_mul_dep") + +(define_bypass 14 "cortex_m4_fdivs" + "cortex_m4_fmacs" + "arm_no_early_mul_dep") diff --git a/gcc/config/arm/cortex-m4.md b/gcc/config/arm/cortex-m4.md new file mode 100644 index 00000000000..b71037585d0 --- /dev/null +++ b/gcc/config/arm/cortex-m4.md @@ -0,0 +1,111 @@ +;; ARM Cortex-M4 pipeline description +;; Copyright (C) 2010 Free Software Foundation, Inc. +;; Contributed by CodeSourcery. +;; +;; 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 3, 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 COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +(define_automaton "cortex_m4") + +;; We model the pipelining of LDR instructions by using two artificial units. + +(define_cpu_unit "cortex_m4_a" "cortex_m4") + +(define_cpu_unit "cortex_m4_b" "cortex_m4") + +(define_reservation "cortex_m4_ex" "cortex_m4_a+cortex_m4_b") + +;; ALU and multiply is one cycle. +(define_insn_reservation "cortex_m4_alu" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "alu,alu_shift,alu_shift_reg,mult")) + "cortex_m4_ex") + +;; Byte, half-word and word load is two cycles. +(define_insn_reservation "cortex_m4_load1" 2 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "load_byte,load1")) + "cortex_m4_a, cortex_m4_b") + +;; str rx, [ry, #imm] is always one cycle. +(define_insn_reservation "cortex_m4_store1_1" 1 + (and (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "store1")) + (ne (symbol_ref ("arm_address_offset_is_imm (insn)")) (const_int 0))) + "cortex_m4_a") + +;; Other byte, half-word and word load is two cycles. +(define_insn_reservation "cortex_m4_store1_2" 2 + (and (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "store1")) + (eq (symbol_ref ("arm_address_offset_is_imm (insn)")) (const_int 0))) + "cortex_m4_a*2") + +(define_insn_reservation "cortex_m4_load2" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "load2")) + "cortex_m4_ex*3") + +(define_insn_reservation "cortex_m4_store2" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "store2")) + "cortex_m4_ex*3") + +(define_insn_reservation "cortex_m4_load3" 4 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "load3")) + "cortex_m4_ex*4") + +(define_insn_reservation "cortex_m4_store3" 4 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "store3")) + "cortex_m4_ex*4") + +(define_insn_reservation "cortex_m4_load4" 5 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "load4")) + "cortex_m4_ex*5") + +(define_insn_reservation "cortex_m4_store4" 5 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "store4")) + "cortex_m4_ex*5") + +;; If the address of load or store depends on the result of the preceding +;; instruction, the latency is increased by one. + +(define_bypass 2 "cortex_m4_alu" + "cortex_m4_load1" + "arm_early_load_addr_dep") + +(define_bypass 2 "cortex_m4_alu" + "cortex_m4_store1_1,cortex_m4_store1_2" + "arm_early_store_addr_dep") + +(define_insn_reservation "cortex_m4_branch" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "branch")) + "cortex_m4_ex*3") + +(define_insn_reservation "cortex_m4_call" 3 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "call")) + "cortex_m4_ex*3") + +(define_insn_reservation "cortex_m4_block" 1 + (and (eq_attr "tune" "cortexm4") + (eq_attr "type" "block")) + "cortex_m4_ex") diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 8e9f1001aba..887c962baeb 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -381,6 +381,10 @@ (define_mode_attr qhs_zextenddi_cond [(SI "") (HI "&& arm_arch6") (QI "")]) (define_mode_attr qhs_sextenddi_cond [(SI "") (HI "&& arm_arch6") (QI "&& arm_arch6")]) +(define_mode_attr qhs_extenddi_op [(SI "s_register_operand") + (HI "nonimmediate_operand") + (QI "nonimmediate_operand")]) +(define_mode_attr qhs_extenddi_cstr [(SI "r") (HI "rm") (QI "rm")]) ;;---------------------------------------------------------------------------- ;; Code attributes diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h index aa0c6614c50..83de685e76c 100644 --- a/gcc/config/avr/avr-protos.h +++ b/gcc/config/avr/avr-protos.h @@ -24,7 +24,6 @@ extern int function_arg_regno_p (int r); extern void avr_cpu_cpp_builtins (struct cpp_reader * pfile); extern int avr_ret_register (void); -extern bool class_likely_spilled_p (int c); extern enum reg_class avr_regno_reg_class (int r); extern void asm_globalize_label (FILE *file, const char *name); extern void avr_asm_declare_function_name (FILE *, const char *, tree); diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index cabf678d8f9..2c7a8ad0204 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -92,6 +92,7 @@ static bool avr_hard_regno_scratch_ok (unsigned int); static unsigned int avr_case_values_threshold (void); static bool avr_frame_pointer_required_p (void); static bool avr_can_eliminate (const int, const int); +static bool avr_class_likely_spilled_p (reg_class_t c); /* Allocate registers from r25 to r8 for parameters for function calls. */ #define FIRST_CUM_REG 26 @@ -193,6 +194,9 @@ static const struct attribute_spec avr_attribute_table[] = #undef TARGET_CAN_ELIMINATE #define TARGET_CAN_ELIMINATE avr_can_eliminate +#undef TARGET_CLASS_LIKELY_SPILLED_P +#define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p + #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE avr_option_override @@ -4762,8 +4766,8 @@ gas_output_ascii(FILE *file, const char *str, size_t length) assigned to registers of class CLASS would likely be spilled because registers of CLASS are needed for spill registers. */ -bool -class_likely_spilled_p (int c) +static bool +avr_class_likely_spilled_p (reg_class_t c) { return (c != ALL_REGS && c != ADDW_REGS); } diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index 92c197a6ab9..60a58993517 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -333,8 +333,6 @@ enum reg_class { #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true -#define CLASS_LIKELY_SPILLED_P(c) class_likely_spilled_p(c) - #define CLASS_MAX_NREGS(CLASS, MODE) class_max_nregs (CLASS, MODE) #define STACK_PUSH_CODE POST_DEC diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 8ff9e2fd0a7..da5a8eef237 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -2543,6 +2543,29 @@ bfin_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, return NO_REGS; } + +/* Implement TARGET_CLASS_LIKELY_SPILLED_P. */ + +static bool +bfin_class_likely_spilled_p (reg_class_t rclass) +{ + switch (rclass) + { + case PREGS_CLOBBERED: + case PROLOGUE_REGS: + case P0REGS: + case D0REGS: + case D1REGS: + case D2REGS: + case CCREGS: + return true; + + default: + break; + } + + return false; +} /* Implement TARGET_HANDLE_OPTION. */ @@ -6635,6 +6658,9 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, #undef TARGET_SECONDARY_RELOAD #define TARGET_SECONDARY_RELOAD bfin_secondary_reload +#undef TARGET_CLASS_LIKELY_SPILLED_P +#define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p + #undef TARGET_DELEGITIMIZE_ADDRESS #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index 037e5be20f7..30b298d76e1 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -750,15 +750,6 @@ enum reg_class registers. */ #define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true -#define CLASS_LIKELY_SPILLED_P(CLASS) \ - ((CLASS) == PREGS_CLOBBERED \ - || (CLASS) == PROLOGUE_REGS \ - || (CLASS) == P0REGS \ - || (CLASS) == D0REGS \ - || (CLASS) == D1REGS \ - || (CLASS) == D2REGS \ - || (CLASS) == CCREGS) - /* Do not allow to store a value in REG_CC for any mode */ /* Do not allow to store value in pregs if mode is not SI*/ #define HARD_REGNO_MODE_OK(REGNO, MODE) hard_regno_mode_ok((REGNO), (MODE)) diff --git a/gcc/config/darwin-driver.c b/gcc/config/darwin-driver.c index b23efc50c0a..1123aa37c43 100644 --- a/gcc/config/darwin-driver.c +++ b/gcc/config/darwin-driver.c @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "gcc.h" +#include "opts.h" #include <sys/sysctl.h> #include "xregex.h" @@ -32,11 +33,12 @@ along with GCC; see the file COPYING3. If not see of the system on which the compiler is running. */ void -darwin_default_min_version (int * argc_p, char *** argv_p) +darwin_default_min_version (unsigned int *decoded_options_count, + struct cl_decoded_option **decoded_options) { - const int argc = *argc_p; - char ** const argv = *argv_p; - int i; + const unsigned int argc = *decoded_options_count; + struct cl_decoded_option *const argv = *decoded_options; + unsigned int i; char osversion[32]; size_t osversion_len = sizeof (osversion) - 1; static int osversion_name[2] = { CTL_KERN, KERN_OSRELEASE }; @@ -44,34 +46,17 @@ darwin_default_min_version (int * argc_p, char *** argv_p) char * version_pend; int major_vers; char minor_vers[6]; - static char new_flag[sizeof ("-mmacosx-version-min=10.0.0") + 6]; + static char new_flag[sizeof ("10.0.0") + 6]; /* If the command-line is empty, just return. */ if (argc <= 1) return; - /* Don't do this if the user has specified -b or -V at the start - of the command-line. */ - if (argv[1][0] == '-' - && (argv[1][1] == 'V' || - ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-'))))) - return; /* Don't do this if the user specified -mmacosx-version-min= or -mno-macosx-version-min. */ for (i = 1; i < argc; i++) - if (argv[i][0] == '-') - { - const char * const p = argv[i]; - if (strncmp (p, "-mno-macosx-version-min", 23) == 0 - || strncmp (p, "-mmacosx-version-min", 20) == 0) - return; - - /* It doesn't count if it's an argument to a different switch. */ - if (p[0] == '-' - && ((SWITCH_TAKES_ARG (p[1]) > (p[2] != 0)) - || WORD_SWITCH_TAKES_ARG (p + 1))) - i++; - } + if (argv[i].opt_index == OPT_mmacosx_version_min_) + return; /* Retrieve the deployment target from the environment and insert it as a flag. */ @@ -84,12 +69,14 @@ darwin_default_min_version (int * argc_p, char *** argv_p) to ignore the environment variable, as if it was never set. */ && macosx_deployment_target[0]) { - ++*argc_p; - *argv_p = XNEWVEC (char *, *argc_p); - (*argv_p)[0] = argv[0]; - (*argv_p)[1] = concat ("-mmacosx-version-min=", - macosx_deployment_target, NULL); - memcpy (*argv_p + 2, argv + 1, (argc - 1) * sizeof (char *)); + ++*decoded_options_count; + *decoded_options = XNEWVEC (struct cl_decoded_option, + *decoded_options_count); + (*decoded_options)[0] = argv[0]; + generate_option (OPT_mmacosx_version_min_, macosx_deployment_target, + 1, CL_DRIVER, &(*decoded_options)[1]); + memcpy (*decoded_options + 2, argv + 1, + (argc - 1) * sizeof (struct cl_decoded_option)); return; } } @@ -128,17 +115,20 @@ darwin_default_min_version (int * argc_p, char *** argv_p) if (major_vers - 4 <= 4) /* On 10.4 and earlier, the old linker is used which does not support three-component system versions. */ - sprintf (new_flag, "-mmacosx-version-min=10.%d", major_vers - 4); + sprintf (new_flag, "10.%d", major_vers - 4); else - sprintf (new_flag, "-mmacosx-version-min=10.%d.%s", major_vers - 4, + sprintf (new_flag, "10.%d.%s", major_vers - 4, minor_vers); /* Add the new flag. */ - ++*argc_p; - *argv_p = XNEWVEC (char *, *argc_p); - (*argv_p)[0] = argv[0]; - (*argv_p)[1] = new_flag; - memcpy (*argv_p + 2, argv + 1, (argc - 1) * sizeof (char *)); + ++*decoded_options_count; + *decoded_options = XNEWVEC (struct cl_decoded_option, + *decoded_options_count); + (*decoded_options)[0] = argv[0]; + generate_option (OPT_mmacosx_version_min_, new_flag, + 1, CL_DRIVER, &(*decoded_options)[1]); + memcpy (*decoded_options + 2, argv + 1, + (argc - 1) * sizeof (struct cl_decoded_option)); return; parse_failed: diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index 3314acb1912..f0ff9010b93 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -1059,9 +1059,10 @@ extern int flag_apple_kext; #define TARGET_HAS_TARGETCM 1 #ifndef CROSS_DIRECTORY_STRUCTURE -extern void darwin_default_min_version (int * argc, char *** argv); +extern void darwin_default_min_version (unsigned int *decoded_options_count, + struct cl_decoded_option **decoded_options); #define GCC_DRIVER_HOST_INITIALIZATION \ - darwin_default_min_version (&argc, &argv) + darwin_default_min_version (&decoded_options_count, &decoded_options) #endif /* CROSS_DIRECTORY_STRUCTURE */ /* The Apple assembler and linker do not support constructor priorities. */ diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index 0730e32d9a4..42d0b1d9d0e 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -4067,7 +4067,7 @@ frv_emit_movsi (rtx dest, rtx src) || (GET_CODE (src) == REG && IN_RANGE_P (REGNO (src), FIRST_VIRTUAL_REGISTER, - LAST_VIRTUAL_REGISTER)))) + LAST_VIRTUAL_POINTER_REGISTER)))) { emit_insn (gen_rtx_SET (VOIDmode, dest, copy_to_mode_reg (SImode, src))); return TRUE; diff --git a/gcc/config/i386/cygwin.asm b/gcc/config/i386/cygwin.asm index 588c12ee701..a6cc94d160a 100644 --- a/gcc/config/i386/cygwin.asm +++ b/gcc/config/i386/cygwin.asm @@ -1,6 +1,7 @@ /* stuff needed for libgcc on win32. * - * Copyright (C) 1996, 1998, 2001, 2003, 2008, 2009 Free Software Foundation, Inc. + * Copyright (C) 1996, 1998, 2001, 2003, 2008, 2009 + * Free Software Foundation, Inc. * Written By Steve Chamberlain * * This file is free software; you can redistribute it and/or modify it @@ -23,104 +24,165 @@ * <http://www.gnu.org/licenses/>. */ -#ifdef L_chkstk +#include "auto-host.h" + +#ifdef HAVE_GAS_CFI_SECTIONS_DIRECTIVE + .cfi_sections .debug_frame +# define cfi_startproc() .cfi_startproc +# define cfi_endproc() .cfi_endproc +# define cfi_adjust_cfa_offset(X) .cfi_adjust_cfa_offset X +# define cfi_def_cfa_register(X) .cfi_def_cfa_register X +# define cfi_register(D,S) .cfi_register D, S +# ifdef _WIN64 +# define cfi_push(X) .cfi_adjust_cfa_offset 8; .cfi_rel_offset X, 0 +# define cfi_pop(X) .cfi_adjust_cfa_offset -8; .cfi_restore X +# else +# define cfi_push(X) .cfi_adjust_cfa_offset 4; .cfi_rel_offset X, 0 +# define cfi_pop(X) .cfi_adjust_cfa_offset -4; .cfi_restore X +# endif +#else +# define cfi_startproc() +# define cfi_endproc() +# define cfi_adjust_cfa_offset(X) +# define cfi_def_cfa_register(X) +# define cfi_register(D,S) +# define cfi_push(X) +# define cfi_pop(X) +#endif /* HAVE_GAS_CFI_SECTIONS_DIRECTIVE */ -/* Function prologue calls _alloca to probe the stack when allocating more +#ifdef L_chkstk +/* Function prologue calls __chkstk to probe the stack when allocating more than CHECK_STACK_LIMIT bytes in one go. Touching the stack at 4K increments is necessary to ensure that the guard pages used by the OS virtual memory manger are allocated in correct sequence. */ .global ___chkstk .global __alloca -#ifndef _WIN64 -___chkstk: +#ifdef _WIN64 +/* __alloca is a normal function call, which uses %rcx as the argument. */ + cfi_startproc() __alloca: - pushl %ecx /* save temp */ - leal 8(%esp), %ecx /* point past return addr */ - cmpl $0x1000, %eax /* > 4k ?*/ - jb Ldone + movq %rcx, %rax + /* FALLTHRU */ -Lprobe: - subl $0x1000, %ecx /* yes, move pointer down 4k*/ - orl $0x0, (%ecx) /* probe there */ - subl $0x1000, %eax /* decrement count */ - cmpl $0x1000, %eax - ja Lprobe /* and do it again */ +/* ___chkstk is a *special* function call, which uses %rax as the argument. + We avoid clobbering the 4 integer argument registers, %rcx, %rdx, + %r8 and %r9, which leaves us with %rax, %r10, and %r11 to use. */ + .align 4 +___chkstk: + popq %r11 /* pop return address */ + cfi_adjust_cfa_offset(-8) /* indicate return address in r11 */ + cfi_register(%rip, %r11) + movq %rsp, %r10 + cmpq $0x1000, %rax /* > 4k ?*/ + jb 2f -Ldone: - subl %eax, %ecx - orl $0x0, (%ecx) /* less than 4k, just peek here */ +1: subq $0x1000, %r10 /* yes, move pointer down 4k*/ + orl $0x0, (%r10) /* probe there */ + subq $0x1000, %rax /* decrement count */ + cmpq $0x1000, %rax + ja 1b /* and do it again */ - movl %esp, %eax /* save old stack pointer */ - movl %ecx, %esp /* decrement stack */ - movl (%eax), %ecx /* recover saved temp */ - movl 4(%eax), %eax /* recover return address */ +2: subq %rax, %r10 + movq %rsp, %rax /* hold CFA until return */ + cfi_def_cfa_register(%rax) + orl $0x0, (%r10) /* less than 4k, just peek here */ + movq %r10, %rsp /* decrement stack */ /* Push the return value back. Doing this instead of just - jumping to %eax preserves the cached call-return stack + jumping to %r11 preserves the cached call-return stack used by most modern processors. */ - pushl %eax + pushq %r11 ret + cfi_endproc() #else -/* __alloca is a normal function call, which uses %rcx as the argument. And stack space - for the argument is saved. */ + cfi_startproc() +___chkstk: __alloca: - movq %rcx, %rax - addq $0x7, %rax - andq $0xfffffffffffffff8, %rax - popq %rcx /* pop return address */ - popq %r10 /* Pop the reserved stack space. */ - movq %rsp, %r10 /* get sp */ - cmpq $0x1000, %rax /* > 4k ?*/ - jb Ldone_alloca - -Lprobe_alloca: - subq $0x1000, %r10 /* yes, move pointer down 4k*/ - orq $0x0, (%r10) /* probe there */ - subq $0x1000, %rax /* decrement count */ - cmpq $0x1000, %rax - ja Lprobe_alloca /* and do it again */ + pushl %ecx /* save temp */ + cfi_push(%eax) + leal 8(%esp), %ecx /* point past return addr */ + cmpl $0x1000, %eax /* > 4k ?*/ + jb 2f + +1: subl $0x1000, %ecx /* yes, move pointer down 4k*/ + orl $0x0, (%ecx) /* probe there */ + subl $0x1000, %eax /* decrement count */ + cmpl $0x1000, %eax + ja 1b /* and do it again */ -Ldone_alloca: - subq %rax, %r10 - orq $0x0, (%r10) /* less than 4k, just peek here */ - movq %r10, %rax - subq $0x8, %r10 /* Reserve argument stack space. */ - movq %r10, %rsp /* decrement stack */ +2: subl %eax, %ecx + orl $0x0, (%ecx) /* less than 4k, just peek here */ + movl %esp, %eax /* save current stack pointer */ + cfi_def_cfa_register(%eax) + movl %ecx, %esp /* decrement stack */ + movl (%eax), %ecx /* recover saved temp */ - /* Push the return value back. Doing this instead of just - jumping to %rcx preserves the cached call-return stack - used by most modern processors. */ - pushq %rcx + /* Copy the return register. Doing this instead of just jumping to + the address preserves the cached call-return stack used by most + modern processors. */ + pushl 4(%eax) ret + cfi_endproc() +#endif /* _WIN64 */ +#endif /* L_chkstk */ -/* ___chkstk is a *special* function call, which uses %rax as the argument. - We avoid clobbering the 4 integer argument registers, %rcx, %rdx, - %r8 and %r9, which leaves us with %rax, %r10, and %r11 to use. */ -___chkstk: - addq $0x7, %rax /* Make sure stack is on alignment of 8. */ - andq $0xfffffffffffffff8, %rax - popq %r11 /* pop return address */ - movq %rsp, %r10 /* get sp */ - cmpq $0x1000, %rax /* > 4k ?*/ - jb Ldone - -Lprobe: - subq $0x1000, %r10 /* yes, move pointer down 4k*/ - orl $0x0, (%r10) /* probe there */ +#ifdef L_chkstk_ms +/* ___chkstk_ms is a *special* function call, which uses %rax as the argument. + We avoid clobbering any registers. Unlike ___chkstk, it just probes the + stack and does no stack allocation. */ + .global ___chkstk_ms +#ifdef _WIN64 + cfi_startproc() +___chkstk_ms: + pushq %rcx /* save temps */ + cfi_push(%rcx) + pushq %rax + cfi_push(%rax) + cmpq $0x1000, %rax /* > 4k ?*/ + leaq 24(%rsp), %rcx /* point past return addr */ + jb 2f + +1: subq $0x1000, %rcx /* yes, move pointer down 4k */ + orq $0x0, (%rcx) /* probe there */ subq $0x1000, %rax /* decrement count */ cmpq $0x1000, %rax - ja Lprobe /* and do it again */ + ja 1b /* and do it again */ -Ldone: - subq %rax, %r10 - orl $0x0, (%r10) /* less than 4k, just peek here */ - movq %r10, %rsp /* decrement stack */ +2: subq %rax, %rcx + orq $0x0, (%rcx) /* less than 4k, just peek here */ - /* Push the return value back. Doing this instead of just - jumping to %r11 preserves the cached call-return stack - used by most modern processors. */ - pushq %r11 + popq %rax + cfi_pop(%rax) + popq %rcx + cfi_pop(%rcx) + ret + cfi_endproc() +#else + cfi_startproc() +___chkstk_ms: + pushl %ecx /* save temp */ + cfi_push(%ecx) + pushl %eax + cfi_push(%eax) + cmpl $0x1000, %eax /* > 4k ?*/ + leal 12(%esp), %ecx /* point past return addr */ + jb 2f + +1: subl $0x1000, %ecx /* yes, move pointer down 4k*/ + orl $0x0, (%ecx) /* probe there */ + subl $0x1000, %eax /* decrement count */ + cmpl $0x1000, %eax + ja 1b /* and do it again */ + +2: subl %eax, %ecx + orl $0x0, (%ecx) /* less than 4k, just peek here */ + + popl %eax + cfi_pop(%eax) + popl %ecx + cfi_pop(%ecx) ret -#endif -#endif + cfi_endproc() +#endif /* _WIN64 */ +#endif /* L_chkstk_ms */ diff --git a/gcc/config/i386/cygwin.h b/gcc/config/i386/cygwin.h index a8d26e9558d..67308fc7dff 100644 --- a/gcc/config/i386/cygwin.h +++ b/gcc/config/i386/cygwin.h @@ -252,12 +252,13 @@ char *cvt_to_mingw[] = #undef GEN_CVT_ARRAY #endif /*GEN_CVT_ARRAY*/ -void mingw_scan (int, const char * const *, const char **); +void mingw_scan (unsigned int, const struct cl_decoded_option *, + const char **); #if 1 #define GCC_DRIVER_HOST_INITIALIZATION \ do \ { \ - mingw_scan(argc, (const char * const *) argv, &spec_machine); \ + mingw_scan (decoded_options_count, decoded_options, &spec_machine); \ } \ while (0) #else @@ -277,7 +278,7 @@ do \ add_prefix (&startfile_prefixes,\ concat (standard_startfile_prefix, "w32api", NULL),\ "GCC", PREFIX_PRIORITY_LAST, 0, NULL);\ - mingw_scan(argc, (const char * const *) argv, &spec_machine); \ + mingw_scan (decoded_options_count, decoded_options, &spec_machine); \ } \ while (0) #endif diff --git a/gcc/config/i386/cygwin1.c b/gcc/config/i386/cygwin1.c index 7de34d24b7a..99d9d8f8243 100644 --- a/gcc/config/i386/cygwin1.c +++ b/gcc/config/i386/cygwin1.c @@ -22,32 +22,42 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "opts.h" #include <string.h> void -mingw_scan (int argc ATTRIBUTE_UNUSED, - const char *const *argv, +mingw_scan (unsigned int decoded_options_count, + const struct cl_decoded_option *decoded_options, const char **spec_machine) { + unsigned int i; putenv (xstrdup ("GCC_CYGWIN_MINGW=0")); - while (*++argv) - if (strcmp (*argv, "-mno-win32") == 0) - putenv (xstrdup ("GCC_CYGWIN_WIN32=0")); - else if (strcmp (*argv, "-mwin32") == 0) - putenv (xstrdup ("GCC_CYGWIN_WIN32=1")); - else if (strcmp (*argv, "-mno-cygwin") == 0) + for (i = 1; i < decoded_options_count; i++) + switch (decoded_options[i].opt_index) { - char *p = strstr (*spec_machine, "-cygwin"); - if (p) + case OPT_mwin32: + if (decoded_options[i].value == 0) + putenv (xstrdup ("GCC_CYGWIN_WIN32=0")); + else + putenv (xstrdup ("GCC_CYGWIN_WIN32=1")); + break; + + case OPT_mcygwin: + if (decoded_options[i].value == 0) { - int len = p - *spec_machine; - char *s = XNEWVEC (char, strlen (*spec_machine) + 3); - memcpy (s, *spec_machine, len); - strcpy (s + len, "-mingw32"); - *spec_machine = s; + char *p = strstr (*spec_machine, "-cygwin"); + if (p) + { + int len = p - *spec_machine; + char *s = XNEWVEC (char, strlen (*spec_machine) + 3); + memcpy (s, *spec_machine, len); + strcpy (s + len, "-mingw32"); + *spec_machine = s; + } + putenv (xstrdup ("GCC_CYGWIN_MINGW=1")); } - putenv (xstrdup ("GCC_CYGWIN_MINGW=1")); + break; } return; } diff --git a/gcc/config/i386/freebsd.h b/gcc/config/i386/freebsd.h index 94b657ec295..1ec5ee0d27d 100644 --- a/gcc/config/i386/freebsd.h +++ b/gcc/config/i386/freebsd.h @@ -147,3 +147,8 @@ along with GCC; see the file COPYING3. If not see /* Static stack checking is supported by means of probes. */ #define STACK_CHECK_STATIC_BUILTIN 1 + +/* Support for i386 has been removed from FreeBSD 6.0 onward. */ +#if FBSD_MAJOR >= 6 +#define SUBTARGET32_DEFAULT_CPU "i486" +#endif diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 909adb9c2b1..fd31e9917f5 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -64,8 +64,7 @@ extern bool legitimate_pic_address_disp_p (rtx); extern void print_reg (rtx, int, FILE*); extern void ix86_print_operand (FILE *, rtx, int); -extern void split_di (rtx[], int, rtx[], rtx[]); -extern void split_ti (rtx[], int, rtx[], rtx[]); +extern void split_double_mode (enum machine_mode, rtx[], int, rtx[], rtx[]); extern const char *output_set_got (rtx, rtx); extern const char *output_387_binary_op (rtx, rtx*); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index dcf887502bc..627d8d20ea0 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1576,6 +1576,9 @@ static unsigned int initial_ix86_tune_features[X86_TUNE_LAST] = { /* X86_TUNE_PAD_RETURNS */ m_AMD_MULTIPLE | m_CORE2 | m_GENERIC, + /* X86_TUNE_PAD_SHORT_FUNCTION: Pad short funtion. */ + m_ATOM, + /* X86_TUNE_EXT_80387_CONSTANTS */ m_K6_GEODE | m_ATHLON_K8 | m_ATOM | m_PENT4 | m_NOCONA | m_PPRO | m_CORE2 | m_GENERIC, @@ -2025,9 +2028,6 @@ static enum calling_abi ix86_function_abi (const_tree); static int ix86_tune_defaulted; static int ix86_arch_specified; -/* Bit flags that specify the ISA we are compiling for. */ -int ix86_isa_flags = TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_ISA_DEFAULT; - /* A mask of ix86_isa_flags that includes bit X if X was set or cleared on the command line. */ static int ix86_isa_flags_explicit; @@ -3661,7 +3661,7 @@ ix86_option_override_internal (bool main_args_p) ix86_gen_one_cmpl2 = gen_one_cmpldi2; ix86_gen_monitor = gen_sse3_monitor64; ix86_gen_andsp = gen_anddi3; - ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_64; + ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_probe_di; ix86_gen_adjust_stack_and_probe = gen_adjust_stack_and_probedi; ix86_gen_probe_stack_range = gen_probe_stack_rangedi; } @@ -3674,7 +3674,7 @@ ix86_option_override_internal (bool main_args_p) ix86_gen_one_cmpl2 = gen_one_cmplsi2; ix86_gen_monitor = gen_sse3_monitor; ix86_gen_andsp = gen_andsi3; - ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_32; + ix86_gen_allocate_stack_worker = gen_allocate_stack_worker_probe_si; ix86_gen_adjust_stack_and_probe = gen_adjust_stack_and_probesi; ix86_gen_probe_stack_range = gen_probe_stack_rangesi; } @@ -7964,12 +7964,12 @@ ix86_code_end (void) rtx xops[2]; int regno; - for (regno = 0; regno < 8; ++regno) + for (regno = AX_REG; regno <= SP_REG; regno++) { char name[32]; tree decl; - if (! ((pic_labels_used >> regno) & 1)) + if (!(pic_labels_used & (1 << regno))) continue; get_pc_thunk_name (name, regno); @@ -8022,10 +8022,20 @@ ix86_code_end (void) /* Make sure unwind info is emitted for the thunk if needed. */ final_start_function (emit_barrier (), asm_out_file, 1); + /* Pad stack IP move with 4 instructions (two NOPs count + as one instruction). */ + if (TARGET_PAD_SHORT_FUNCTION) + { + int i = 8; + + while (i--) + fputs ("\tnop\n", asm_out_file); + } + xops[0] = gen_rtx_REG (Pmode, regno); xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx); output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops); - output_asm_insn ("ret", xops); + fputs ("\tret\n", asm_out_file); final_end_function (); init_insn_lengths (); free_after_compilation (cfun); @@ -8767,9 +8777,9 @@ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, rtx insn; if (! TARGET_64BIT) - insn = emit_insn (gen_pro_epilogue_adjust_stack_si_1 (dest, src, offset)); + insn = gen_pro_epilogue_adjust_stack_si_add (dest, src, offset); else if (x86_64_immediate_operand (offset, DImode)) - insn = emit_insn (gen_pro_epilogue_adjust_stack_di_1 (dest, src, offset)); + insn = gen_pro_epilogue_adjust_stack_di_add (dest, src, offset); else { rtx tmp; @@ -8786,10 +8796,11 @@ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, insn = emit_insn (gen_rtx_SET (DImode, tmp, offset)); if (style < 0) RTX_FRAME_RELATED_P (insn) = 1; - insn = emit_insn (gen_pro_epilogue_adjust_stack_di_2 (dest, src, tmp, - offset)); + + insn = gen_pro_epilogue_adjust_stack_di_add (dest, src, tmp); } + insn = emit_insn (insn); if (style >= 0) ix86_add_queued_cfa_restore_notes (insn); @@ -9688,38 +9699,64 @@ ix86_expand_prologue (void) else { rtx eax = gen_rtx_REG (Pmode, AX_REG); - bool eax_live; + rtx r10 = NULL; + rtx (*adjust_stack_insn)(rtx, rtx, rtx); - if (cfun->machine->call_abi == MS_ABI) - eax_live = false; - else - eax_live = ix86_eax_live_at_start_p (); + bool eax_live = false; + bool r10_live = false; + + if (TARGET_64BIT) + r10_live = (DECL_STATIC_CHAIN (current_function_decl) != 0); + if (!TARGET_64BIT_MS_ABI) + eax_live = ix86_eax_live_at_start_p (); if (eax_live) { emit_insn (gen_push (eax)); allocate -= UNITS_PER_WORD; } + if (r10_live) + { + r10 = gen_rtx_REG (Pmode, R10_REG); + emit_insn (gen_push (r10)); + allocate -= UNITS_PER_WORD; + } emit_move_insn (eax, GEN_INT (allocate)); + emit_insn (ix86_gen_allocate_stack_worker (eax, eax)); - insn = emit_insn (ix86_gen_allocate_stack_worker (eax, eax)); + /* Use the fact that AX still contains ALLOCATE. */ + adjust_stack_insn = (TARGET_64BIT + ? gen_pro_epilogue_adjust_stack_di_sub + : gen_pro_epilogue_adjust_stack_si_sub); + + insn = emit_insn (adjust_stack_insn (stack_pointer_rtx, + stack_pointer_rtx, eax)); if (m->fs.cfa_reg == stack_pointer_rtx) { m->fs.cfa_offset += allocate; - t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-allocate)); - t = gen_rtx_SET (VOIDmode, stack_pointer_rtx, t); - add_reg_note (insn, REG_CFA_ADJUST_CFA, t); + RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_ADJUST_CFA, + gen_rtx_SET (VOIDmode, stack_pointer_rtx, + plus_constant (stack_pointer_rtx, + -allocate))); } m->fs.sp_offset += allocate; - if (eax_live) - { + if (r10_live && eax_live) + { t = choose_baseaddr (m->fs.sp_offset - allocate); + emit_move_insn (r10, gen_frame_mem (Pmode, t)); + t = choose_baseaddr (m->fs.sp_offset - allocate - UNITS_PER_WORD); emit_move_insn (eax, gen_frame_mem (Pmode, t)); } + else if (eax_live || r10_live) + { + t = choose_baseaddr (m->fs.sp_offset - allocate); + emit_move_insn ((eax_live ? eax : r10), gen_frame_mem (Pmode, t)); + } } gcc_assert (m->fs.sp_offset == frame.stack_pointer_offset); @@ -13243,15 +13280,33 @@ i386_asm_output_addr_const_extra (FILE *file, rtx x) return true; } -/* Split one or more DImode RTL references into pairs of SImode +/* Split one or more double-mode RTL references into pairs of half-mode references. The RTL can be REG, offsettable MEM, integer constant, or - CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to + CONST_DOUBLE. "operands" is a pointer to an array of double-mode RTLs to split and "num" is its length. lo_half and hi_half are output arrays that parallel "operands". */ void -split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[]) +split_double_mode (enum machine_mode mode, rtx operands[], + int num, rtx lo_half[], rtx hi_half[]) { + enum machine_mode half_mode; + unsigned int byte; + + switch (mode) + { + case TImode: + half_mode = DImode; + break; + case DImode: + half_mode = SImode; + break; + default: + gcc_unreachable (); + } + + byte = GET_MODE_SIZE (half_mode); + while (num--) { rtx op = operands[num]; @@ -13260,44 +13315,17 @@ split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[]) but we still have to handle it. */ if (MEM_P (op)) { - lo_half[num] = adjust_address (op, SImode, 0); - hi_half[num] = adjust_address (op, SImode, 4); + lo_half[num] = adjust_address (op, half_mode, 0); + hi_half[num] = adjust_address (op, half_mode, byte); } else { - lo_half[num] = simplify_gen_subreg (SImode, op, + lo_half[num] = simplify_gen_subreg (half_mode, op, GET_MODE (op) == VOIDmode - ? DImode : GET_MODE (op), 0); - hi_half[num] = simplify_gen_subreg (SImode, op, + ? mode : GET_MODE (op), 0); + hi_half[num] = simplify_gen_subreg (half_mode, op, GET_MODE (op) == VOIDmode - ? DImode : GET_MODE (op), 4); - } - } -} -/* Split one or more TImode RTL references into pairs of DImode - references. The RTL can be REG, offsettable MEM, integer constant, or - CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to - split and "num" is its length. lo_half and hi_half are output arrays - that parallel "operands". */ - -void -split_ti (rtx operands[], int num, rtx lo_half[], rtx hi_half[]) -{ - while (num--) - { - rtx op = operands[num]; - - /* simplify_subreg refuse to split volatile memory addresses, but we - still have to handle it. */ - if (MEM_P (op)) - { - lo_half[num] = adjust_address (op, DImode, 0); - hi_half[num] = adjust_address (op, DImode, 8); - } - else - { - lo_half[num] = simplify_gen_subreg (DImode, op, TImode, 0); - hi_half[num] = simplify_gen_subreg (DImode, op, TImode, 8); + ? mode : GET_MODE (op), byte); } } } @@ -16268,9 +16296,10 @@ ix86_expand_compare (enum rtx_code code, rtx op0, rtx op1) void ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label) { + enum machine_mode mode = GET_MODE (op0); rtx tmp; - switch (GET_MODE (op0)) + switch (mode) { case SFmode: case DFmode: @@ -16301,18 +16330,11 @@ ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label) tmp = op0, op0 = op1, op1 = tmp; code = swap_condition (code); } - if (GET_MODE (op0) == DImode) - { - split_di (&op0, 1, lo+0, hi+0); - split_di (&op1, 1, lo+1, hi+1); - submode = SImode; - } - else - { - split_ti (&op0, 1, lo+0, hi+0); - split_ti (&op1, 1, lo+1, hi+1); - submode = DImode; - } + + split_double_mode (mode, &op0, 1, lo+0, hi+0); + split_double_mode (mode, &op1, 1, lo+1, hi+1); + + submode = mode == DImode ? SImode : DImode; /* When comparing for equality, we can use (hi0^hi1)|(lo0^lo1) to avoid two branches. This costs one extra insn, so disable when @@ -16469,7 +16491,7 @@ ix86_expand_carry_flag_compare (enum rtx_code code, rtx op0, rtx op1, rtx *pop) enum machine_mode mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1); - /* Do not handle DImode compares that go through special path. */ + /* Do not handle double-mode compares that go through special path. */ if (mode == (TARGET_64BIT ? TImode : DImode)) return false; @@ -17681,8 +17703,8 @@ ix86_expand_int_addcc (rtx operands[]) } -/* Split operands 0 and 1 into SImode parts. Similar to split_di, but - works for floating pointer parameters and nonoffsetable memories. +/* Split operands 0 and 1 into half-mode parts. Similar to split_double_mode, + but works for floating pointer parameters and nonoffsetable memories. For pushes, it returns just stack offsets; the values will be saved in the right order. Maximally three parts are generated. */ @@ -17735,7 +17757,7 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode) if (!TARGET_64BIT) { if (mode == DImode) - split_di (&operand, 1, &parts[0], &parts[1]); + split_double_mode (mode, &operand, 1, &parts[0], &parts[1]); else { int i; @@ -17786,7 +17808,7 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode) else { if (mode == TImode) - split_ti (&operand, 1, &parts[0], &parts[1]); + split_double_mode (mode, &operand, 1, &parts[0], &parts[1]); if (mode == XFmode || mode == TFmode) { enum machine_mode upper_mode = mode==XFmode ? SImode : DImode; @@ -17857,7 +17879,7 @@ ix86_split_long_move (rtx operands[]) /* The DFmode expanders may ask us to move double. For 64bit target this is single move. By hiding the fact here we simplify i386.md splitters. */ - if (GET_MODE_SIZE (GET_MODE (operands[0])) == 8 && TARGET_64BIT) + if (TARGET_64BIT && GET_MODE_SIZE (GET_MODE (operands[0])) == 8) { /* Optimize constant pool reference to immediates. This is used by fp moves, that force all constants to memory to allow combining. */ @@ -18067,62 +18089,62 @@ ix86_split_long_move (rtx operands[]) static void ix86_expand_ashl_const (rtx operand, int count, enum machine_mode mode) { - if (count == 1) + rtx (*insn)(rtx, rtx, rtx); + + if (count == 1 + || (count * ix86_cost->add <= ix86_cost->shift_const + && !optimize_insn_for_size_p ())) { - emit_insn ((mode == DImode - ? gen_addsi3 - : gen_adddi3) (operand, operand, operand)); + insn = mode == DImode ? gen_addsi3 : gen_adddi3; + while (count-- > 0) + emit_insn (insn (operand, operand, operand)); } - else if (!optimize_insn_for_size_p () - && count * ix86_cost->add <= ix86_cost->shift_const) + else { - int i; - for (i=0; i<count; i++) - { - emit_insn ((mode == DImode - ? gen_addsi3 - : gen_adddi3) (operand, operand, operand)); - } + insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3; + emit_insn (insn (operand, operand, GEN_INT (count))); } - else - emit_insn ((mode == DImode - ? gen_ashlsi3 - : gen_ashldi3) (operand, operand, GEN_INT (count))); } void ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode) { + rtx (*gen_ashl3)(rtx, rtx, rtx); + rtx (*gen_shld)(rtx, rtx, rtx); + int half_width = GET_MODE_BITSIZE (mode) >> 1; + rtx low[2], high[2]; int count; - const int single_width = mode == DImode ? 32 : 64; if (CONST_INT_P (operands[2])) { - (mode == DImode ? split_di : split_ti) (operands, 2, low, high); - count = INTVAL (operands[2]) & (single_width * 2 - 1); + split_double_mode (mode, operands, 2, low, high); + count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1); - if (count >= single_width) + if (count >= half_width) { emit_move_insn (high[0], low[1]); emit_move_insn (low[0], const0_rtx); - if (count > single_width) - ix86_expand_ashl_const (high[0], count - single_width, mode); + if (count > half_width) + ix86_expand_ashl_const (high[0], count - half_width, mode); } else { + gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld; + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - emit_insn ((mode == DImode - ? gen_x86_shld - : gen_x86_64_shld) (high[0], low[0], GEN_INT (count))); + + emit_insn (gen_shld (high[0], low[0], GEN_INT (count))); ix86_expand_ashl_const (low[0], count, mode); } return; } - (mode == DImode ? split_di : split_ti) (operands, 1, low, high); + split_double_mode (mode, operands, 1, low, high); + + gen_ashl3 = mode == DImode ? gen_ashlsi3 : gen_ashldi3; if (operands[1] == const1_rtx) { @@ -18134,7 +18156,7 @@ ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode) ix86_expand_clear (low[0]); ix86_expand_clear (high[0]); - emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (single_width))); + emit_insn (gen_testqi_ccz_1 (operands[2], GEN_INT (half_width))); d = gen_lowpart (QImode, low[0]); d = gen_rtx_STRICT_LOW_PART (VOIDmode, d); @@ -18154,33 +18176,44 @@ ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode) pentium4 a bit; no one else seems to care much either way. */ else { + enum machine_mode half_mode; + rtx (*gen_lshr3)(rtx, rtx, rtx); + rtx (*gen_and3)(rtx, rtx, rtx); + rtx (*gen_xor3)(rtx, rtx, rtx); + HOST_WIDE_INT bits; rtx x; + if (mode == DImode) + { + half_mode = SImode; + gen_lshr3 = gen_lshrsi3; + gen_and3 = gen_andsi3; + gen_xor3 = gen_xorsi3; + bits = 5; + } + else + { + half_mode = DImode; + gen_lshr3 = gen_lshrdi3; + gen_and3 = gen_anddi3; + gen_xor3 = gen_xordi3; + bits = 6; + } + if (TARGET_PARTIAL_REG_STALL && !optimize_insn_for_size_p ()) - x = gen_rtx_ZERO_EXTEND (mode == DImode ? SImode : DImode, operands[2]); + x = gen_rtx_ZERO_EXTEND (half_mode, operands[2]); else - x = gen_lowpart (mode == DImode ? SImode : DImode, operands[2]); + x = gen_lowpart (half_mode, operands[2]); emit_insn (gen_rtx_SET (VOIDmode, high[0], x)); - emit_insn ((mode == DImode - ? gen_lshrsi3 - : gen_lshrdi3) (high[0], high[0], - GEN_INT (mode == DImode ? 5 : 6))); - emit_insn ((mode == DImode - ? gen_andsi3 - : gen_anddi3) (high[0], high[0], const1_rtx)); + emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (bits))); + emit_insn (gen_and3 (high[0], high[0], const1_rtx)); emit_move_insn (low[0], high[0]); - emit_insn ((mode == DImode - ? gen_xorsi3 - : gen_xordi3) (low[0], low[0], const1_rtx)); + emit_insn (gen_xor3 (low[0], low[0], const1_rtx)); } - emit_insn ((mode == DImode - ? gen_ashlsi3 - : gen_ashldi3) (low[0], low[0], operands[2])); - emit_insn ((mode == DImode - ? gen_ashlsi3 - : gen_ashldi3) (high[0], high[0], operands[2])); + emit_insn (gen_ashl3 (low[0], low[0], operands[2])); + emit_insn (gen_ashl3 (high[0], high[0], operands[2])); return; } @@ -18196,176 +18229,177 @@ ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode) } else { + gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld; + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - (mode == DImode ? split_di : split_ti) (operands, 1, low, high); - emit_insn ((mode == DImode - ? gen_x86_shld - : gen_x86_64_shld) (high[0], low[0], operands[2])); + split_double_mode (mode, operands, 1, low, high); + emit_insn (gen_shld (high[0], low[0], operands[2])); } - emit_insn ((mode == DImode - ? gen_ashlsi3 - : gen_ashldi3) (low[0], low[0], operands[2])); + emit_insn (gen_ashl3 (low[0], low[0], operands[2])); if (TARGET_CMOVE && scratch) { + rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1; + ix86_expand_clear (scratch); - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_1 - : gen_x86_shiftdi_adj_1) (high[0], low[0], operands[2], - scratch)); + emit_insn (gen_x86_shift_adj_1 (high[0], low[0], operands[2], scratch)); } else - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_2 - : gen_x86_shiftdi_adj_2) (high[0], low[0], operands[2])); + { + rtx (*gen_x86_shift_adj_2)(rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_2 : gen_x86_shiftdi_adj_2; + + emit_insn (gen_x86_shift_adj_2 (high[0], low[0], operands[2])); + } } void ix86_split_ashr (rtx *operands, rtx scratch, enum machine_mode mode) { + rtx (*gen_ashr3)(rtx, rtx, rtx) + = mode == DImode ? gen_ashrsi3 : gen_ashrdi3; + rtx (*gen_shrd)(rtx, rtx, rtx); + int half_width = GET_MODE_BITSIZE (mode) >> 1; + rtx low[2], high[2]; int count; - const int single_width = mode == DImode ? 32 : 64; if (CONST_INT_P (operands[2])) { - (mode == DImode ? split_di : split_ti) (operands, 2, low, high); - count = INTVAL (operands[2]) & (single_width * 2 - 1); + split_double_mode (mode, operands, 2, low, high); + count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1); - if (count == single_width * 2 - 1) + if (count == GET_MODE_BITSIZE (mode) - 1) { emit_move_insn (high[0], high[1]); - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (high[0], high[0], - GEN_INT (single_width - 1))); + emit_insn (gen_ashr3 (high[0], high[0], + GEN_INT (half_width - 1))); emit_move_insn (low[0], high[0]); } - else if (count >= single_width) + else if (count >= half_width) { emit_move_insn (low[0], high[1]); emit_move_insn (high[0], low[0]); - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (high[0], high[0], - GEN_INT (single_width - 1))); - if (count > single_width) - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (low[0], low[0], - GEN_INT (count - single_width))); + emit_insn (gen_ashr3 (high[0], high[0], + GEN_INT (half_width - 1))); + + if (count > half_width) + emit_insn (gen_ashr3 (low[0], low[0], + GEN_INT (count - half_width))); } else { + gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd; + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - emit_insn ((mode == DImode - ? gen_x86_shrd - : gen_x86_64_shrd) (low[0], high[0], GEN_INT (count))); - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (high[0], high[0], GEN_INT (count))); + + emit_insn (gen_shrd (low[0], high[0], GEN_INT (count))); + emit_insn (gen_ashr3 (high[0], high[0], GEN_INT (count))); } } else { - if (!rtx_equal_p (operands[0], operands[1])) + gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd; + + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - (mode == DImode ? split_di : split_ti) (operands, 1, low, high); + split_double_mode (mode, operands, 1, low, high); - emit_insn ((mode == DImode - ? gen_x86_shrd - : gen_x86_64_shrd) (low[0], high[0], operands[2])); - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (high[0], high[0], operands[2])); + emit_insn (gen_shrd (low[0], high[0], operands[2])); + emit_insn (gen_ashr3 (high[0], high[0], operands[2])); if (TARGET_CMOVE && scratch) { + rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1; + emit_move_insn (scratch, high[0]); - emit_insn ((mode == DImode - ? gen_ashrsi3 - : gen_ashrdi3) (scratch, scratch, - GEN_INT (single_width - 1))); - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_1 - : gen_x86_shiftdi_adj_1) (low[0], high[0], operands[2], - scratch)); + emit_insn (gen_ashr3 (scratch, scratch, + GEN_INT (half_width - 1))); + emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2], + scratch)); } else - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_3 - : gen_x86_shiftdi_adj_3) (low[0], high[0], operands[2])); + { + rtx (*gen_x86_shift_adj_3)(rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_3 : gen_x86_shiftdi_adj_3; + + emit_insn (gen_x86_shift_adj_3 (low[0], high[0], operands[2])); + } } } void ix86_split_lshr (rtx *operands, rtx scratch, enum machine_mode mode) { + rtx (*gen_lshr3)(rtx, rtx, rtx) + = mode == DImode ? gen_lshrsi3 : gen_lshrdi3; + rtx (*gen_shrd)(rtx, rtx, rtx); + int half_width = GET_MODE_BITSIZE (mode) >> 1; + rtx low[2], high[2]; int count; - const int single_width = mode == DImode ? 32 : 64; if (CONST_INT_P (operands[2])) { - (mode == DImode ? split_di : split_ti) (operands, 2, low, high); - count = INTVAL (operands[2]) & (single_width * 2 - 1); + split_double_mode (mode, operands, 2, low, high); + count = INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1); - if (count >= single_width) + if (count >= half_width) { emit_move_insn (low[0], high[1]); ix86_expand_clear (high[0]); - if (count > single_width) - emit_insn ((mode == DImode - ? gen_lshrsi3 - : gen_lshrdi3) (low[0], low[0], - GEN_INT (count - single_width))); + if (count > half_width) + emit_insn (gen_lshr3 (low[0], low[0], + GEN_INT (count - half_width))); } else { + gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd; + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - emit_insn ((mode == DImode - ? gen_x86_shrd - : gen_x86_64_shrd) (low[0], high[0], GEN_INT (count))); - emit_insn ((mode == DImode - ? gen_lshrsi3 - : gen_lshrdi3) (high[0], high[0], GEN_INT (count))); + + emit_insn (gen_shrd (low[0], high[0], GEN_INT (count))); + emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (count))); } } else { + gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd; + if (!rtx_equal_p (operands[0], operands[1])) emit_move_insn (operands[0], operands[1]); - (mode == DImode ? split_di : split_ti) (operands, 1, low, high); + split_double_mode (mode, operands, 1, low, high); - emit_insn ((mode == DImode - ? gen_x86_shrd - : gen_x86_64_shrd) (low[0], high[0], operands[2])); - emit_insn ((mode == DImode - ? gen_lshrsi3 - : gen_lshrdi3) (high[0], high[0], operands[2])); + emit_insn (gen_shrd (low[0], high[0], operands[2])); + emit_insn (gen_lshr3 (high[0], high[0], operands[2])); - /* Heh. By reversing the arguments, we can reuse this pattern. */ if (TARGET_CMOVE && scratch) { + rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1; + ix86_expand_clear (scratch); - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_1 - : gen_x86_shiftdi_adj_1) (low[0], high[0], operands[2], - scratch)); + emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2], + scratch)); } else - emit_insn ((mode == DImode - ? gen_x86_shiftsi_adj_2 - : gen_x86_shiftdi_adj_2) (low[0], high[0], operands[2])); + { + rtx (*gen_x86_shift_adj_2)(rtx, rtx, rtx) + = mode == DImode ? gen_x86_shiftsi_adj_2 : gen_x86_shiftdi_adj_2; + + emit_insn (gen_x86_shift_adj_2 (low[0], high[0], operands[2])); + } } } @@ -18402,10 +18436,10 @@ ix86_expand_aligntest (rtx variable, int value, bool epilogue) static void ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value) { - if (GET_MODE (countreg) == DImode) - emit_insn (gen_adddi3 (countreg, countreg, GEN_INT (-value))); - else - emit_insn (gen_addsi3 (countreg, countreg, GEN_INT (-value))); + rtx (*gen_add)(rtx, rtx, rtx) + = GET_MODE (countreg) == DImode ? gen_adddi3 : gen_addsi3; + + emit_insn (gen_add (countreg, countreg, GEN_INT (-value))); } /* Zero extend possibly SImode EXP to Pmode register. */ @@ -19221,7 +19255,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, { unsigned int i; enum stringop_alg alg = libcall; - for (i = 0; i < NAX_STRINGOP_ALGS; i++) + for (i = 0; i < MAX_STRINGOP_ALGS; i++) { /* We get here if the algorithms that were not libcall-based were rep-prefix based and we are unable to use rep prefixes @@ -19267,7 +19301,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, int i; bool any_alg_usable_p = true; - for (i = 0; i < NAX_STRINGOP_ALGS; i++) + for (i = 0; i < MAX_STRINGOP_ALGS; i++) { enum stringop_alg candidate = algs->size[i].alg; any_alg_usable_p = any_alg_usable_p && ALG_USABLE_P (candidate); @@ -26139,7 +26173,7 @@ ix86_force_to_memory (enum machine_mode mode, rtx operand) case DImode: { rtx operands[2]; - split_di (&operand, 1, operands, operands + 1); + split_double_mode (mode, &operand, 1, operands, operands + 1); emit_insn ( gen_rtx_SET (VOIDmode, gen_rtx_MEM (SImode, @@ -27885,6 +27919,120 @@ ix86_pad_returns (void) } } +/* Count the minimum number of instructions in BB. Return 4 if the + number of instructions >= 4. */ + +static int +ix86_count_insn_bb (basic_block bb) +{ + rtx insn; + int insn_count = 0; + + /* Count number of instructions in this block. Return 4 if the number + of instructions >= 4. */ + FOR_BB_INSNS (bb, insn) + { + /* Only happen in exit blocks. */ + if (JUMP_P (insn) + && GET_CODE (PATTERN (insn)) == RETURN) + break; + + if (NONDEBUG_INSN_P (insn) + && GET_CODE (PATTERN (insn)) != USE + && GET_CODE (PATTERN (insn)) != CLOBBER) + { + insn_count++; + if (insn_count >= 4) + return insn_count; + } + } + + return insn_count; +} + + +/* Count the minimum number of instructions in code path in BB. + Return 4 if the number of instructions >= 4. */ + +static int +ix86_count_insn (basic_block bb) +{ + edge e; + edge_iterator ei; + int min_prev_count; + + /* Only bother counting instructions along paths with no + more than 2 basic blocks between entry and exit. Given + that BB has an edge to exit, determine if a predecessor + of BB has an edge from entry. If so, compute the number + of instructions in the predecessor block. If there + happen to be multiple such blocks, compute the minimum. */ + min_prev_count = 4; + FOR_EACH_EDGE (e, ei, bb->preds) + { + edge prev_e; + edge_iterator prev_ei; + + if (e->src == ENTRY_BLOCK_PTR) + { + min_prev_count = 0; + break; + } + FOR_EACH_EDGE (prev_e, prev_ei, e->src->preds) + { + if (prev_e->src == ENTRY_BLOCK_PTR) + { + int count = ix86_count_insn_bb (e->src); + if (count < min_prev_count) + min_prev_count = count; + break; + } + } + } + + if (min_prev_count < 4) + min_prev_count += ix86_count_insn_bb (bb); + + return min_prev_count; +} + +/* Pad short funtion to 4 instructions. */ + +static void +ix86_pad_short_function (void) +{ + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds) + { + rtx ret = BB_END (e->src); + if (JUMP_P (ret) && GET_CODE (PATTERN (ret)) == RETURN) + { + int insn_count = ix86_count_insn (e->src); + + /* Pad short function. */ + if (insn_count < 4) + { + rtx insn = ret; + + /* Find epilogue. */ + while (insn + && (!NOTE_P (insn) + || NOTE_KIND (insn) != NOTE_INSN_EPILOGUE_BEG)) + insn = PREV_INSN (insn); + + if (!insn) + insn = ret; + + /* Two NOPs are counted as one instruction. */ + insn_count = 2 * (4 - insn_count); + emit_insn_before (gen_nops (GEN_INT (insn_count)), insn); + } + } + } +} + /* Implement machine specific optimizations. We implement padding of returns for K8 CPUs and pass to avoid 4 jumps in the single 16 byte window. */ static void @@ -27892,7 +28040,9 @@ ix86_reorg (void) { if (optimize && optimize_function_for_speed_p (cfun)) { - if (TARGET_PAD_RETURNS) + if (TARGET_PAD_SHORT_FUNCTION) + ix86_pad_short_function (); + else if (TARGET_PAD_RETURNS) ix86_pad_returns (); #ifdef ASM_OUTPUT_MAX_SKIP_PAD if (TARGET_FOUR_JUMP_LIMIT) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 22dd02b0bb8..b3439bc9f0c 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -90,7 +90,7 @@ enum stringop_alg unrolled_loop }; -#define NAX_STRINGOP_ALGS 4 +#define MAX_STRINGOP_ALGS 4 /* Specify what algorithm to use for stringops on known size. When size is unknown, the UNKNOWN_SIZE alg is used. When size is @@ -107,7 +107,7 @@ struct stringop_algs const struct stringop_strategy { const int max; const enum stringop_alg alg; - } size [NAX_STRINGOP_ALGS]; + } size [MAX_STRINGOP_ALGS]; }; /* Define the specific costs for a given cpu */ @@ -299,6 +299,7 @@ enum ix86_tune_indices { X86_TUNE_USE_BT, X86_TUNE_USE_INCDEC, X86_TUNE_PAD_RETURNS, + X86_TUNE_PAD_SHORT_FUNCTION, X86_TUNE_EXT_80387_CONSTANTS, X86_TUNE_SHORTEN_X87_SSE, X86_TUNE_AVOID_VECTOR_DECODE, @@ -385,6 +386,8 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST]; #define TARGET_USE_BT ix86_tune_features[X86_TUNE_USE_BT] #define TARGET_USE_INCDEC ix86_tune_features[X86_TUNE_USE_INCDEC] #define TARGET_PAD_RETURNS ix86_tune_features[X86_TUNE_PAD_RETURNS] +#define TARGET_PAD_SHORT_FUNCTION \ + ix86_tune_features[X86_TUNE_PAD_SHORT_FUNCTION] #define TARGET_EXT_80387_CONSTANTS \ ix86_tune_features[X86_TUNE_EXT_80387_CONSTANTS] #define TARGET_SHORTEN_X87_SSE ix86_tune_features[X86_TUNE_SHORTEN_X87_SSE] @@ -671,9 +674,8 @@ enum target_cpu_default /* Width of a word, in units (bytes). */ #define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4) -#ifdef IN_LIBGCC2 -#define MIN_UNITS_PER_WORD (TARGET_64BIT ? 8 : 4) -#else + +#ifndef IN_LIBGCC2 #define MIN_UNITS_PER_WORD 4 #endif @@ -860,8 +862,8 @@ enum target_cpu_default #define STACK_REGS #define IS_STACK_MODE(MODE) \ - (((MODE) == SFmode && (!TARGET_SSE || !TARGET_SSE_MATH)) \ - || ((MODE) == DFmode && (!TARGET_SSE2 || !TARGET_SSE_MATH)) \ + (((MODE) == SFmode && !(TARGET_SSE && TARGET_SSE_MATH)) \ + || ((MODE) == DFmode && !(TARGET_SSE2 && TARGET_SSE_MATH)) \ || (MODE) == XFmode) /* Cover class containing the stack registers. */ @@ -976,8 +978,7 @@ enum target_cpu_default Actually there are no two word move instructions for consecutive registers. And only registers 0-3 may have mov byte instructions - applied to them. - */ + applied to them. */ #define HARD_REGNO_NREGS(REGNO, MODE) \ (FP_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO) \ @@ -1184,7 +1185,8 @@ enum reg_class NON_Q_REGS, /* %esi %edi %ebp %esp */ INDEX_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp */ LEGACY_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp */ - GENERAL_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp %r8 - %r15*/ + GENERAL_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp + %r8 %r9 %r10 %r11 %r12 %r13 %r14 %r15 */ FP_TOP_REG, FP_SECOND_REG, /* %st(0) %st(1) */ FLOAT_REGS, SSE_FIRST_REG, @@ -1413,10 +1415,13 @@ enum reg_class /* On the 80386, this is the size of MODE in words, except in the FP regs, where a single reg is always enough. */ #define CLASS_MAX_NREGS(CLASS, MODE) \ - (!MAYBE_INTEGER_CLASS_P (CLASS) \ - ? (COMPLEX_MODE_P (MODE) ? 2 : 1) \ - : (((((MODE) == XFmode ? 12 : GET_MODE_SIZE (MODE))) \ - + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + (MAYBE_INTEGER_CLASS_P (CLASS) \ + ? ((MODE) == XFmode \ + ? (TARGET_64BIT ? 2 : 3) \ + : (MODE) == XCmode \ + ? (TARGET_64BIT ? 4 : 6) \ + : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) \ + : (COMPLEX_MODE_P (MODE) ? 2 : 1)) /* Return a class of registers that cannot change FROM mode to TO mode. */ @@ -1750,7 +1755,7 @@ typedef struct ix86_args { /* MOVE_MAX_PIECES is the number of bytes at a time which we can move efficiently, as opposed to MOVE_MAX which is the maximum number of bytes we can move with a single instruction. */ -#define MOVE_MAX_PIECES (TARGET_64BIT ? 8 : 4) +#define MOVE_MAX_PIECES UNITS_PER_WORD /* If a memory-to-memory move would take MOVE_RATIO or more simple move-instruction pairs, we will do a movmem or libcall instead. @@ -1995,18 +2000,12 @@ do { \ #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ ix86_output_addr_diff_elt ((FILE), (VALUE), (REL)) -/* When we see %v, we will print the 'v' prefix if TARGET_AVX is - true. */ +/* When we see %v, we will print the 'v' prefix if TARGET_AVX is true. */ #define ASM_OUTPUT_AVX_PREFIX(STREAM, PTR) \ { \ if ((PTR)[0] == '%' && (PTR)[1] == 'v') \ - { \ - if (TARGET_AVX) \ - (PTR) += 1; \ - else \ - (PTR) += 2; \ - } \ + (PTR) += TARGET_AVX ? 1 : 2; \ } /* A C statement or statements which output an assembler instruction diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index ec43793b951..c541c1485c4 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -247,6 +247,7 @@ UNSPECV_LOCK UNSPECV_PROLOGUE_USE UNSPECV_CLD + UNSPECV_NOPS UNSPECV_VZEROALL UNSPECV_VZEROUPPER UNSPECV_RDTSC @@ -1639,7 +1640,7 @@ [(set (match_dup 0) (match_dup 1)) (set (match_dup 2) (match_dup 3))] { - split_di (&operands[1], 1, &operands[2], &operands[3]); + split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]); operands[1] = gen_lowpart (DImode, operands[2]); operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx, @@ -1656,7 +1657,7 @@ [(set (match_dup 0) (match_dup 1)) (set (match_dup 2) (match_dup 3))] { - split_di (&operands[1], 1, &operands[2], &operands[3]); + split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]); operands[1] = gen_lowpart (DImode, operands[2]); operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx, @@ -2049,7 +2050,7 @@ && !x86_64_immediate_operand (operands[1], DImode) && 1" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] - "split_di (&operands[0], 2, &operands[2], &operands[4]);") + "split_double_mode (DImode, &operands[0], 2, &operands[2], &operands[4]);") (define_split [(set (match_operand:DI 0 "memory_operand" "") @@ -2060,7 +2061,7 @@ && !x86_64_immediate_operand (operands[1], DImode)" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] - "split_di (&operands[0], 2, &operands[2], &operands[4]);") + "split_double_mode (DImode, &operands[0], 2, &operands[2], &operands[4]);") (define_insn "*movdi_internal" [(set (match_operand:DI 0 "nonimmediate_operand" @@ -3597,7 +3598,7 @@ (zero_extend:DI (match_dup 0)))] "TARGET_64BIT" [(set (match_dup 4) (const_int 0))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") + "split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]);") ;; %%% Kill me once multi-word ops are sane. (define_insn "zero_extendsidi2_1" @@ -3625,7 +3626,7 @@ "!TARGET_64BIT && reload_completed && true_regnum (operands[0]) == true_regnum (operands[1])" [(set (match_dup 4) (const_int 0))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") + "split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]);") (define_split [(set (match_operand:DI 0 "nonimmediate_operand" "") @@ -3635,7 +3636,7 @@ && !(MMX_REG_P (operands[0]) || SSE_REG_P (operands[0]))" [(set (match_dup 3) (match_dup 1)) (set (match_dup 4) (const_int 0))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") + "split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]);") (define_insn "zero_extend<mode>di2" [(set (match_operand:DI 0 "register_operand" "=r") @@ -3800,7 +3801,7 @@ (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31))) (clobber (reg:CC FLAGS_REG))]) (set (match_dup 4) (match_dup 1))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") + "split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]);") ;; Extend to memory case when source register does not die. (define_split @@ -3811,7 +3812,7 @@ "reload_completed" [(const_int 0)] { - split_di (&operands[0], 1, &operands[3], &operands[4]); + split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]); emit_move_insn (operands[3], operands[1]); @@ -3841,7 +3842,7 @@ "reload_completed" [(const_int 0)] { - split_di (&operands[0], 1, &operands[3], &operands[4]); + split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]); if (true_regnum (operands[3]) != true_regnum (operands[1])) emit_move_insn (operands[3], operands[1]); @@ -5569,7 +5570,7 @@ (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) (match_dup 5)))) (clobber (reg:CC FLAGS_REG))])] - "split_<dwi> (&operands[0], 3, &operands[0], &operands[3]);") + "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);") (define_insn "*add<mode>3_cc" [(set (reg:CC FLAGS_REG) @@ -6599,7 +6600,7 @@ (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) (match_dup 5)))) (clobber (reg:CC FLAGS_REG))])] - "split_<dwi> (&operands[0], 3, &operands[0], &operands[3]);") + "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);") (define_insn "*sub<mode>_1" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") @@ -8592,7 +8593,7 @@ [(set (match_dup 2) (neg:DWIH (match_dup 2))) (clobber (reg:CC FLAGS_REG))])] - "split_<dwi> (&operands[0], 2, &operands[0], &operands[2]);") + "split_double_mode (<DWI>mode, &operands[0], 2, &operands[0], &operands[2]);") (define_insn "*neg<mode>2_1" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m") @@ -10071,7 +10072,7 @@ { operands[6] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)); - split_<dwi> (&operands[0], 1, &operands[4], &operands[5]); + split_double_mode (<DWI>mode, &operands[0], 1, &operands[4], &operands[5]); }) (define_insn_and_split "ix86_rotr<dwi>3_doubleword" @@ -10099,7 +10100,7 @@ { operands[6] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)); - split_<dwi> (&operands[0], 1, &operands[4], &operands[5]); + split_double_mode (<DWI>mode, &operands[0], 1, &operands[4], &operands[5]); }) (define_insn "*<rotate_insn><mode>3_1" @@ -11465,6 +11466,25 @@ (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) +;; Generate nops. Operand 0 is the number of nops, up to 8. +(define_insn "nops" + [(unspec_volatile [(match_operand 0 "const_int_operand" "")] + UNSPECV_NOPS)] + "reload_completed" +{ + int num = INTVAL (operands[0]); + + gcc_assert (num >= 1 && num <= 8); + + while (num--) + fputs ("\tnop\n", asm_out_file); + + return ""; +} + [(set (attr "length") (symbol_ref "INTVAL (operands[0])")) + (set_attr "length_immediate" "0") + (set_attr "modrm" "0")]) + ;; Pad to 16-byte boundary, max skip in op0. Used to avoid ;; branch prediction penalty for the third jump in a 16-byte ;; block on K8. @@ -11495,7 +11515,7 @@ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" - { return output_set_got (operands[0], NULL_RTX); } + "* return output_set_got (operands[0], NULL_RTX);" [(set_attr "type" "multi") (set_attr "length" "12")]) @@ -11505,7 +11525,7 @@ UNSPEC_SET_GOT)) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" - { return output_set_got (operands[0], operands[1]); } + "* return output_set_got (operands[0], operands[1]);" [(set_attr "type" "multi") (set_attr "length" "12")]) @@ -14960,18 +14980,65 @@ DONE; }) -(define_expand "signbit<mode>2" +(define_expand "signbitxf2" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:XF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387" +{ + rtx scratch = gen_reg_rtx (HImode); + + emit_insn (gen_fxamxf2_i387 (scratch, operands[1])); + emit_insn (gen_andsi3 (operands[0], + gen_lowpart (SImode, scratch), GEN_INT (0x200))); + DONE; +}) + +(define_insn "movmsk_df" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI + [(match_operand:DF 1 "register_operand" "x")] + UNSPEC_MOVMSK))] + "SSE_FLOAT_MODE_P (DFmode) && TARGET_SSE_MATH" + "%vmovmskpd\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") + (set_attr "prefix" "maybe_vex") + (set_attr "mode" "DF")]) + +;; Use movmskpd in SSE mode to avoid store forwarding stall +;; for 32bit targets and movq+shrq sequence for 64bit targets. +(define_expand "signbitdf2" [(use (match_operand:SI 0 "register_operand" "")) - (use (match_operand:X87MODEF 1 "register_operand" ""))] + (use (match_operand:DF 1 "register_operand" ""))] "TARGET_USE_FANCY_MATH_387 - && !(SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH)" + || (SSE_FLOAT_MODE_P (DFmode) && TARGET_SSE_MATH)" { - rtx mask = GEN_INT (0x0200); + if (SSE_FLOAT_MODE_P (DFmode) && TARGET_SSE_MATH) + { + emit_insn (gen_movmsk_df (operands[0], operands[1])); + emit_insn (gen_andsi3 (operands[0], operands[0], const1_rtx)); + } + else + { + rtx scratch = gen_reg_rtx (HImode); + emit_insn (gen_fxamdf2_i387 (scratch, operands[1])); + emit_insn (gen_andsi3 (operands[0], + gen_lowpart (SImode, scratch), GEN_INT (0x200))); + } + DONE; +}) + +(define_expand "signbitsf2" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:SF 1 "register_operand" ""))] + "TARGET_USE_FANCY_MATH_387 + && !(SSE_FLOAT_MODE_P (SFmode) && TARGET_SSE_MATH)" +{ rtx scratch = gen_reg_rtx (HImode); - emit_insn (gen_fxam<mode>2_i387 (scratch, operands[1])); - emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, scratch), mask)); + emit_insn (gen_fxamsf2_i387 (scratch, operands[1])); + emit_insn (gen_andsi3 (operands[0], + gen_lowpart (SImode, scratch), GEN_INT (0x200))); DONE; }) @@ -16021,8 +16088,8 @@ (match_dup 7) (match_dup 8)))] { - split_di (&operands[2], 2, &operands[5], &operands[7]); - split_di (&operands[0], 1, &operands[2], &operands[3]); + split_double_mode (DImode, &operands[2], 2, &operands[5], &operands[7]); + split_double_mode (DImode, &operands[0], 1, &operands[2], &operands[3]); }) (define_insn "*movxfcc_1" @@ -16179,10 +16246,10 @@ ;; ;; in proper program order. -(define_insn "pro_epilogue_adjust_stack_<mode>_1" +(define_insn "pro_epilogue_adjust_stack_<mode>_add" [(set (match_operand:P 0 "register_operand" "=r,r") (plus:P (match_operand:P 1 "register_operand" "0,r") - (match_operand:P 2 "<immediate_operand>" "<i>,<i>"))) + (match_operand:P 2 "<nonmemory_operand>" "r<i>,l<i>"))) (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))] "" @@ -16222,52 +16289,24 @@ (const_string "*"))) (set_attr "mode" "<MODE>")]) -(define_insn "pro_epilogue_adjust_stack_di_2" - [(set (match_operand:DI 0 "register_operand" "=r,r") - (plus:DI (match_operand:DI 1 "register_operand" "0,r") - (match_operand:DI 3 "immediate_operand" "i,i"))) - (use (match_operand:DI 2 "register_operand" "r,l")) +(define_insn "pro_epilogue_adjust_stack_<mode>_sub" + [(set (match_operand:P 0 "register_operand" "=r") + (minus:P (match_operand:P 1 "register_operand" "0") + (match_operand:P 2 "register_operand" "r"))) (clobber (reg:CC FLAGS_REG)) (clobber (mem:BLK (scratch)))] - "TARGET_64BIT" -{ - switch (get_attr_type (insn)) - { - case TYPE_ALU: - return "add{q}\t{%2, %0|%0, %2}"; - - case TYPE_LEA: - operands[2] = gen_rtx_PLUS (DImode, operands[1], operands[2]); - return "lea{q}\t{%a2, %0|%0, %a2}"; - - default: - gcc_unreachable (); - } -} - [(set_attr "type" "alu,lea") - (set_attr "mode" "DI")]) - -(define_insn "allocate_stack_worker_32" - [(set (match_operand:SI 0 "register_operand" "=a") - (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "0")] - UNSPECV_STACK_PROBE)) - (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 1))) - (clobber (reg:CC FLAGS_REG))] - "!TARGET_64BIT && ix86_target_stack_probe ()" - "call\t___chkstk" - [(set_attr "type" "multi") - (set_attr "length" "5")]) + "" + "sub{<imodesuffix>}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "mode" "<MODE>")]) -(define_insn "allocate_stack_worker_64" - [(set (match_operand:DI 0 "register_operand" "=a") - (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "0")] +(define_insn "allocate_stack_worker_probe_<mode>" + [(set (match_operand:P 0 "register_operand" "=a") + (unspec_volatile:P [(match_operand:P 1 "register_operand" "0")] UNSPECV_STACK_PROBE)) - (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 1))) - (clobber (reg:DI R10_REG)) - (clobber (reg:DI R11_REG)) (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_target_stack_probe ()" - "call\t___chkstk" + "ix86_target_stack_probe ()" + "call\t___chkstk_ms" [(set_attr "type" "multi") (set_attr "length" "5")]) @@ -16292,15 +16331,15 @@ } else { - rtx (*gen_allocate_stack_worker) (rtx, rtx); - + x = copy_to_mode_reg (Pmode, operands[1]); if (TARGET_64BIT) - gen_allocate_stack_worker = gen_allocate_stack_worker_64; + emit_insn (gen_allocate_stack_worker_probe_di (x, x)); else - gen_allocate_stack_worker = gen_allocate_stack_worker_32; - - x = copy_to_mode_reg (Pmode, operands[1]); - emit_insn (gen_allocate_stack_worker (x, x)); + emit_insn (gen_allocate_stack_worker_probe_si (x, x)); + x = expand_simple_binop (Pmode, MINUS, stack_pointer_rtx, x, + stack_pointer_rtx, 0, OPTAB_DIRECT); + if (x != stack_pointer_rtx) + emit_move_insn (stack_pointer_rtx, x); } emit_move_insn (operands[0], virtual_stack_dynamic_rtx); diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index aa78cdfaa26..38a53f616c7 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -19,6 +19,10 @@ ; along with GCC; see the file COPYING3. If not see ; <http://www.gnu.org/licenses/>. +; Bit flags that specify the ISA we are compiling for. +Variable +int ix86_isa_flags = TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_ISA_DEFAULT + ;; Definitions to add to the cl_target_option structure ;; -march= processor TargetSave diff --git a/gcc/config/i386/t-cygming b/gcc/config/i386/t-cygming index 0a65ffd99d9..183e545d8eb 100644 --- a/gcc/config/i386/t-cygming +++ b/gcc/config/i386/t-cygming @@ -17,7 +17,7 @@ # <http://www.gnu.org/licenses/>. LIB1ASMSRC = i386/cygwin.asm -LIB1ASMFUNCS = _chkstk +LIB1ASMFUNCS = _chkstk _chkstk_ms # cygwin and mingw always have a limits.h, but, depending upon how we are # doing the build, it may not be installed yet. diff --git a/gcc/config/i386/t-cygwin b/gcc/config/i386/t-cygwin index af91aa5cdb6..a01219cfb9d 100644 --- a/gcc/config/i386/t-cygwin +++ b/gcc/config/i386/t-cygwin @@ -1,4 +1,4 @@ -# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009 +# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010 # Free Software Foundation, Inc. # # This file is part of GCC. @@ -24,7 +24,7 @@ LIBGCC2_INCLUDES += -I$(srcdir)/../winsup/include \ -I$(srcdir)/../winsup/cygwin/include cygwin1.o: $(srcdir)/config/i386/cygwin1.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - $(TM_H) $(TM_P_H) + $(TM_H) $(TM_P_H) opts.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/i386/cygwin1.c diff --git a/gcc/config/i386/t-interix b/gcc/config/i386/t-interix index 9a25831f135..30539e2e13f 100644 --- a/gcc/config/i386/t-interix +++ b/gcc/config/i386/t-interix @@ -1,5 +1,5 @@ LIB1ASMSRC = i386/cygwin.asm -LIB1ASMFUNCS = _chkstk +LIB1ASMFUNCS = _chkstk _chkstk_ms winnt.o: $(srcdir)/config/i386/winnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \ diff --git a/gcc/config/i386/vx-common.h b/gcc/config/i386/vx-common.h index cc7ea75ce40..f4547f08848 100644 --- a/gcc/config/i386/vx-common.h +++ b/gcc/config/i386/vx-common.h @@ -24,3 +24,9 @@ along with GCC; see the file COPYING3. If not see #define SUBTARGET_RETURN_IN_MEMORY(TYPE, FNTYPE) \ ix86_solaris_return_in_memory (TYPE, FNTYPE) + +/* Provide our target specific DBX_REGISTER_NUMBER, as advertised by the + common svr4.h. VxWorks relies on the SVR4 numbering. */ + +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n] diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index d02d2b8fc3f..61be5a45bbe 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -230,7 +230,6 @@ static void emit_predicate_relation_info (void); static void ia64_reorg (void); static bool ia64_in_small_data_p (const_tree); static void process_epilogue (FILE *, rtx, bool, bool); -static int process_set (FILE *, rtx, rtx, bool, bool); static bool ia64_assemble_integer (rtx, unsigned int, int); static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT); @@ -318,6 +317,8 @@ static enum machine_mode ia64_promote_function_mode (const_tree, int); static void ia64_trampoline_init (rtx, tree, rtx); static void ia64_override_options_after_change (void); + +static void ia64_dwarf_handle_frame_unspec (const char *, rtx, int); /* Table of valid machine attributes. */ static const struct attribute_spec ia64_attribute_table[] = @@ -527,6 +528,8 @@ static const struct attribute_spec ia64_attribute_table[] = #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg +#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC +#define TARGET_DWARF_HANDLE_FRAME_UNSPEC ia64_dwarf_handle_frame_unspec #undef TARGET_ASM_UNWIND_EMIT #define TARGET_ASM_UNWIND_EMIT ia64_asm_unwind_emit #undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY @@ -3035,7 +3038,7 @@ do_spill (rtx (*move_fn) (rtx, rtx, rtx), rtx reg, HOST_WIDE_INT cfa_off, off = current_frame_info.total_size - cfa_off; } - add_reg_note (insn, REG_FRAME_RELATED_EXPR, + add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (VOIDmode, gen_rtx_MEM (GET_MODE (reg), plus_constant (base, off)), @@ -3219,6 +3222,10 @@ ia64_expand_prologue (void) { insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); RTX_FRAME_RELATED_P (insn) = 1; + + /* Force the unwind info to recognize this as defining a new CFA, + rather than some temp register setup. */ + add_reg_note (insn, REG_CFA_ADJUST_CFA, NULL_RTX); } if (current_frame_info.total_size != 0) @@ -3241,13 +3248,12 @@ ia64_expand_prologue (void) if (! frame_pointer_needed) { RTX_FRAME_RELATED_P (insn) = 1; - if (GET_CODE (offset) != CONST_INT) - add_reg_note (insn, REG_FRAME_RELATED_EXPR, - gen_rtx_SET (VOIDmode, - stack_pointer_rtx, - gen_rtx_PLUS (DImode, - stack_pointer_rtx, - frame_size_rtx))); + add_reg_note (insn, REG_CFA_ADJUST_CFA, + gen_rtx_SET (VOIDmode, + stack_pointer_rtx, + gen_rtx_PLUS (DImode, + stack_pointer_rtx, + frame_size_rtx))); } /* ??? At this point we must generate a magic insn that appears to @@ -3275,7 +3281,11 @@ ia64_expand_prologue (void) reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM); insn = emit_move_insn (ar_unat_save_reg, reg); - RTX_FRAME_RELATED_P (insn) = (current_frame_info.r[reg_save_ar_unat] != 0); + if (current_frame_info.r[reg_save_ar_unat]) + { + RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX); + } /* Even if we're not going to generate an epilogue, we still need to save the register so that EH works. */ @@ -3314,8 +3324,7 @@ ia64_expand_prologue (void) /* ??? Denote pr spill/fill by a DImode move that modifies all 64 hard registers. */ RTX_FRAME_RELATED_P (insn) = 1; - add_reg_note (insn, REG_FRAME_RELATED_EXPR, - gen_rtx_SET (VOIDmode, alt_reg, reg)); + add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX); /* Even if we're not going to generate an epilogue, we still need to save the register so that EH works. */ @@ -3361,6 +3370,7 @@ ia64_expand_prologue (void) reg_emitted (reg_save_ar_lc); insn = emit_move_insn (alt_reg, reg); RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX); /* Even if we're not going to generate an epilogue, we still need to save the register so that EH works. */ @@ -3387,6 +3397,7 @@ ia64_expand_prologue (void) reg_emitted (reg_save_b0); insn = emit_move_insn (alt_reg, reg); RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX); /* Even if we're not going to generate an epilogue, we still need to save the register so that EH works. */ @@ -3677,6 +3688,7 @@ ia64_expand_epilogue (int sibcall_p) { insn = emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_ADJUST_CFA, NULL); } else if (current_frame_info.total_size) { @@ -3696,13 +3708,12 @@ ia64_expand_epilogue (int sibcall_p) offset)); RTX_FRAME_RELATED_P (insn) = 1; - if (GET_CODE (offset) != CONST_INT) - add_reg_note (insn, REG_FRAME_RELATED_EXPR, - gen_rtx_SET (VOIDmode, - stack_pointer_rtx, - gen_rtx_PLUS (DImode, - stack_pointer_rtx, - frame_size_rtx))); + add_reg_note (insn, REG_CFA_ADJUST_CFA, + gen_rtx_SET (VOIDmode, + stack_pointer_rtx, + gen_rtx_PLUS (DImode, + stack_pointer_rtx, + frame_size_rtx))); } if (cfun->machine->ia64_eh_epilogue_bsp) @@ -3713,11 +3724,12 @@ ia64_expand_epilogue (int sibcall_p) else { int fp = GR_REG (2); - /* We need a throw away register here, r0 and r1 are reserved, so r2 is the - first available call clobbered register. If there was a frame_pointer - register, we may have swapped the names of r2 and HARD_FRAME_POINTER_REGNUM, - so we have to make sure we're using the string "r2" when emitting - the register name for the assembler. */ + /* We need a throw away register here, r0 and r1 are reserved, + so r2 is the first available call clobbered register. If + there was a frame_pointer register, we may have swapped the + names of r2 and HARD_FRAME_POINTER_REGNUM, so we have to make + sure we're using the string "r2" when emitting the register + name for the assembler. */ if (current_frame_info.r[reg_fp] && current_frame_info.r[reg_fp] == GR_REG (2)) fp = HARD_FRAME_POINTER_REGNUM; @@ -9590,6 +9602,17 @@ ia64_dwarf2out_def_steady_cfa (rtx insn, bool frame) + ARG_POINTER_CFA_OFFSET (current_function_decl)); } +/* All we need to do here is avoid a crash in the generic dwarf2 + processing. The real CFA definition is set up above. */ + +static void +ia64_dwarf_handle_frame_unspec (const char * ARG_UNUSED (label), + rtx ARG_UNUSED (pattern), + int index) +{ + gcc_assert (index == UNSPECV_ALLOC); +} + /* The generic dwarf2 frame debug info generator does not define a separate region for the very end of the epilogue, so refrain from doing so in the IA64-specific code as well. */ @@ -9619,53 +9642,19 @@ process_epilogue (FILE *asm_out_file, rtx insn, bool unwind, bool frame) STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET); } -/* This function processes a SET pattern looking for specific patterns - which result in emitting an assembly directive required for unwinding. */ +/* This function processes a SET pattern for REG_CFA_ADJUST_CFA. */ -static int -process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) +static void +process_cfa_adjust_cfa (FILE *asm_out_file, rtx pat, rtx insn, + bool unwind, bool frame) { - rtx src = SET_SRC (pat); rtx dest = SET_DEST (pat); - int src_regno, dest_regno; - - /* Look for the ALLOC insn. */ - if (GET_CODE (src) == UNSPEC_VOLATILE - && XINT (src, 1) == UNSPECV_ALLOC - && GET_CODE (dest) == REG) - { - dest_regno = REGNO (dest); - - /* If this is the final destination for ar.pfs, then this must - be the alloc in the prologue. */ - if (dest_regno == current_frame_info.r[reg_save_ar_pfs]) - { - if (unwind) - fprintf (asm_out_file, "\t.save ar.pfs, r%d\n", - ia64_dbx_register_number (dest_regno)); - } - else - { - /* This must be an alloc before a sibcall. We must drop the - old frame info. The easiest way to drop the old frame - info is to ensure we had a ".restore sp" directive - followed by a new prologue. If the procedure doesn't - have a memory-stack frame, we'll issue a dummy ".restore - sp" now. */ - if (current_frame_info.total_size == 0 && !frame_pointer_needed) - /* if haven't done process_epilogue() yet, do it now */ - process_epilogue (asm_out_file, insn, unwind, frame); - if (unwind) - fprintf (asm_out_file, "\t.prologue\n"); - } - return 1; - } + rtx src = SET_SRC (pat); - /* Look for SP = .... */ - if (GET_CODE (dest) == REG && REGNO (dest) == STACK_POINTER_REGNUM) + if (dest == stack_pointer_rtx) { if (GET_CODE (src) == PLUS) - { + { rtx op0 = XEXP (src, 0); rtx op1 = XEXP (src, 1); @@ -9675,7 +9664,8 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) { gcc_assert (!frame_pointer_needed); if (unwind) - fprintf (asm_out_file, "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n", + fprintf (asm_out_file, + "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n", -INTVAL (op1)); ia64_dwarf2out_def_steady_cfa (insn, frame); } @@ -9684,240 +9674,303 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) } else { - gcc_assert (GET_CODE (src) == REG - && REGNO (src) == HARD_FRAME_POINTER_REGNUM); + gcc_assert (src == hard_frame_pointer_rtx); process_epilogue (asm_out_file, insn, unwind, frame); } + } + else if (dest == hard_frame_pointer_rtx) + { + gcc_assert (src == stack_pointer_rtx); + gcc_assert (frame_pointer_needed); - return 1; + if (unwind) + fprintf (asm_out_file, "\t.vframe r%d\n", + ia64_dbx_register_number (REGNO (dest))); + ia64_dwarf2out_def_steady_cfa (insn, frame); } + else + gcc_unreachable (); +} - /* Register move we need to look at. */ - if (GET_CODE (dest) == REG && GET_CODE (src) == REG) - { - src_regno = REGNO (src); - dest_regno = REGNO (dest); +/* This function processes a SET pattern for REG_CFA_REGISTER. */ - switch (src_regno) - { - case BR_REG (0): - /* Saving return address pointer. */ - gcc_assert (dest_regno == current_frame_info.r[reg_save_b0]); - if (unwind) - fprintf (asm_out_file, "\t.save rp, r%d\n", - ia64_dbx_register_number (dest_regno)); - return 1; +static void +process_cfa_register (FILE *asm_out_file, rtx pat, bool unwind) +{ + rtx dest = SET_DEST (pat); + rtx src = SET_SRC (pat); - case PR_REG (0): - gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]); - if (unwind) - fprintf (asm_out_file, "\t.save pr, r%d\n", - ia64_dbx_register_number (dest_regno)); - return 1; + int dest_regno = REGNO (dest); + int src_regno = REGNO (src); - case AR_UNAT_REGNUM: - gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]); - if (unwind) - fprintf (asm_out_file, "\t.save ar.unat, r%d\n", - ia64_dbx_register_number (dest_regno)); - return 1; + switch (src_regno) + { + case BR_REG (0): + /* Saving return address pointer. */ + gcc_assert (dest_regno == current_frame_info.r[reg_save_b0]); + if (unwind) + fprintf (asm_out_file, "\t.save rp, r%d\n", + ia64_dbx_register_number (dest_regno)); + break; - case AR_LC_REGNUM: - gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]); - if (unwind) - fprintf (asm_out_file, "\t.save ar.lc, r%d\n", - ia64_dbx_register_number (dest_regno)); - return 1; + case PR_REG (0): + gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]); + if (unwind) + fprintf (asm_out_file, "\t.save pr, r%d\n", + ia64_dbx_register_number (dest_regno)); + break; - case STACK_POINTER_REGNUM: - gcc_assert (dest_regno == HARD_FRAME_POINTER_REGNUM - && frame_pointer_needed); - if (unwind) - fprintf (asm_out_file, "\t.vframe r%d\n", - ia64_dbx_register_number (dest_regno)); - ia64_dwarf2out_def_steady_cfa (insn, frame); - return 1; + case AR_UNAT_REGNUM: + gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]); + if (unwind) + fprintf (asm_out_file, "\t.save ar.unat, r%d\n", + ia64_dbx_register_number (dest_regno)); + break; - default: - /* Everything else should indicate being stored to memory. */ - gcc_unreachable (); - } + case AR_LC_REGNUM: + gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]); + if (unwind) + fprintf (asm_out_file, "\t.save ar.lc, r%d\n", + ia64_dbx_register_number (dest_regno)); + break; + + default: + /* Everything else should indicate being stored to memory. */ + gcc_unreachable (); } +} - /* Memory store we need to look at. */ - if (GET_CODE (dest) == MEM && GET_CODE (src) == REG) - { - long off; - rtx base; - const char *saveop; +/* This function processes a SET pattern for REG_CFA_OFFSET. */ - if (GET_CODE (XEXP (dest, 0)) == REG) - { - base = XEXP (dest, 0); - off = 0; - } - else - { - gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS - && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT); - base = XEXP (XEXP (dest, 0), 0); - off = INTVAL (XEXP (XEXP (dest, 0), 1)); - } +static void +process_cfa_offset (FILE *asm_out_file, rtx pat, bool unwind) +{ + rtx dest = SET_DEST (pat); + rtx src = SET_SRC (pat); + int src_regno = REGNO (src); + const char *saveop; + HOST_WIDE_INT off; + rtx base; - if (base == hard_frame_pointer_rtx) - { - saveop = ".savepsp"; - off = - off; - } - else - { - gcc_assert (base == stack_pointer_rtx); - saveop = ".savesp"; - } + gcc_assert (MEM_P (dest)); + if (GET_CODE (XEXP (dest, 0)) == REG) + { + base = XEXP (dest, 0); + off = 0; + } + else + { + gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS + && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT); + base = XEXP (XEXP (dest, 0), 0); + off = INTVAL (XEXP (XEXP (dest, 0), 1)); + } - src_regno = REGNO (src); - switch (src_regno) - { - case BR_REG (0): - gcc_assert (!current_frame_info.r[reg_save_b0]); - if (unwind) - fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off); - return 1; + if (base == hard_frame_pointer_rtx) + { + saveop = ".savepsp"; + off = - off; + } + else + { + gcc_assert (base == stack_pointer_rtx); + saveop = ".savesp"; + } - case PR_REG (0): - gcc_assert (!current_frame_info.r[reg_save_pr]); - if (unwind) - fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off); - return 1; + src_regno = REGNO (src); + switch (src_regno) + { + case BR_REG (0): + gcc_assert (!current_frame_info.r[reg_save_b0]); + if (unwind) + fprintf (asm_out_file, "\t%s rp, " HOST_WIDE_INT_PRINT_DEC "\n", + saveop, off); + break; - case AR_LC_REGNUM: - gcc_assert (!current_frame_info.r[reg_save_ar_lc]); - if (unwind) - fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off); - return 1; + case PR_REG (0): + gcc_assert (!current_frame_info.r[reg_save_pr]); + if (unwind) + fprintf (asm_out_file, "\t%s pr, " HOST_WIDE_INT_PRINT_DEC "\n", + saveop, off); + break; - case AR_PFS_REGNUM: - gcc_assert (!current_frame_info.r[reg_save_ar_pfs]); - if (unwind) - fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off); - return 1; + case AR_LC_REGNUM: + gcc_assert (!current_frame_info.r[reg_save_ar_lc]); + if (unwind) + fprintf (asm_out_file, "\t%s ar.lc, " HOST_WIDE_INT_PRINT_DEC "\n", + saveop, off); + break; - case AR_UNAT_REGNUM: - gcc_assert (!current_frame_info.r[reg_save_ar_unat]); - if (unwind) - fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off); - return 1; + case AR_PFS_REGNUM: + gcc_assert (!current_frame_info.r[reg_save_ar_pfs]); + if (unwind) + fprintf (asm_out_file, "\t%s ar.pfs, " HOST_WIDE_INT_PRINT_DEC "\n", + saveop, off); + break; - case GR_REG (4): - case GR_REG (5): - case GR_REG (6): - case GR_REG (7): - if (unwind) - fprintf (asm_out_file, "\t.save.g 0x%x\n", - 1 << (src_regno - GR_REG (4))); - return 1; + case AR_UNAT_REGNUM: + gcc_assert (!current_frame_info.r[reg_save_ar_unat]); + if (unwind) + fprintf (asm_out_file, "\t%s ar.unat, " HOST_WIDE_INT_PRINT_DEC "\n", + saveop, off); + break; - case BR_REG (1): - case BR_REG (2): - case BR_REG (3): - case BR_REG (4): - case BR_REG (5): - if (unwind) - fprintf (asm_out_file, "\t.save.b 0x%x\n", - 1 << (src_regno - BR_REG (1))); - return 1; + case GR_REG (4): + case GR_REG (5): + case GR_REG (6): + case GR_REG (7): + if (unwind) + fprintf (asm_out_file, "\t.save.g 0x%x\n", + 1 << (src_regno - GR_REG (4))); + break; - case FR_REG (2): - case FR_REG (3): - case FR_REG (4): - case FR_REG (5): - if (unwind) - fprintf (asm_out_file, "\t.save.f 0x%x\n", - 1 << (src_regno - FR_REG (2))); - return 1; + case BR_REG (1): + case BR_REG (2): + case BR_REG (3): + case BR_REG (4): + case BR_REG (5): + if (unwind) + fprintf (asm_out_file, "\t.save.b 0x%x\n", + 1 << (src_regno - BR_REG (1))); + break; - case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19): - case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23): - case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27): - case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31): - if (unwind) - fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n", - 1 << (src_regno - FR_REG (12))); - return 1; + case FR_REG (2): + case FR_REG (3): + case FR_REG (4): + case FR_REG (5): + if (unwind) + fprintf (asm_out_file, "\t.save.f 0x%x\n", + 1 << (src_regno - FR_REG (2))); + break; - default: - return 0; - } - } + case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19): + case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23): + case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27): + case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31): + if (unwind) + fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n", + 1 << (src_regno - FR_REG (12))); + break; - return 0; + default: + /* ??? For some reason we mark other general registers, even those + we can't represent in the unwind info. Ignore them. */ + break; + } } - /* This function looks at a single insn and emits any directives required to unwind this insn. */ + static void ia64_asm_unwind_emit (FILE *asm_out_file, rtx insn) { bool unwind = (flag_unwind_tables || (flag_exceptions && !USING_SJLJ_EXCEPTIONS)); bool frame = dwarf2out_do_frame (); + rtx note, pat; + bool handled_one; + + if (!unwind && !frame) + return; - if (unwind || frame) + if (NOTE_INSN_BASIC_BLOCK_P (insn)) { - rtx pat; + last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR; - if (NOTE_INSN_BASIC_BLOCK_P (insn)) + /* Restore unwind state from immediately before the epilogue. */ + if (need_copy_state) { - last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR; - - /* Restore unwind state from immediately before the epilogue. */ - if (need_copy_state) + if (unwind) { - if (unwind) - { - fprintf (asm_out_file, "\t.body\n"); - fprintf (asm_out_file, "\t.copy_state %d\n", - cfun->machine->state_num); - } - if (IA64_CHANGE_CFA_IN_EPILOGUE) - ia64_dwarf2out_def_steady_cfa (insn, frame); - need_copy_state = false; + fprintf (asm_out_file, "\t.body\n"); + fprintf (asm_out_file, "\t.copy_state %d\n", + cfun->machine->state_num); } + if (IA64_CHANGE_CFA_IN_EPILOGUE) + ia64_dwarf2out_def_steady_cfa (insn, frame); + need_copy_state = false; } + } - if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn)) - return; + if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn)) + return; + + /* Look for the ALLOC insn. */ + if (INSN_CODE (insn) == CODE_FOR_alloc) + { + rtx dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0)); + int dest_regno = REGNO (dest); - pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX); - if (pat) - pat = XEXP (pat, 0); + /* If this is the final destination for ar.pfs, then this must + be the alloc in the prologue. */ + if (dest_regno == current_frame_info.r[reg_save_ar_pfs]) + { + if (unwind) + fprintf (asm_out_file, "\t.save ar.pfs, r%d\n", + ia64_dbx_register_number (dest_regno)); + } else - pat = PATTERN (insn); + { + /* This must be an alloc before a sibcall. We must drop the + old frame info. The easiest way to drop the old frame + info is to ensure we had a ".restore sp" directive + followed by a new prologue. If the procedure doesn't + have a memory-stack frame, we'll issue a dummy ".restore + sp" now. */ + if (current_frame_info.total_size == 0 && !frame_pointer_needed) + /* if haven't done process_epilogue() yet, do it now */ + process_epilogue (asm_out_file, insn, unwind, frame); + if (unwind) + fprintf (asm_out_file, "\t.prologue\n"); + } + return; + } - switch (GET_CODE (pat)) - { - case SET: - process_set (asm_out_file, pat, insn, unwind, frame); - break; + handled_one = false; + for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) + switch (REG_NOTE_KIND (note)) + { + case REG_CFA_ADJUST_CFA: + pat = XEXP (note, 0); + if (pat == NULL) + pat = PATTERN (insn); + process_cfa_adjust_cfa (asm_out_file, pat, insn, unwind, frame); + handled_one = true; + break; - case PARALLEL: - { - int par_index; - int limit = XVECLEN (pat, 0); - for (par_index = 0; par_index < limit; par_index++) - { - rtx x = XVECEXP (pat, 0, par_index); - if (GET_CODE (x) == SET) - process_set (asm_out_file, x, insn, unwind, frame); - } - break; - } + case REG_CFA_OFFSET: + pat = XEXP (note, 0); + if (pat == NULL) + pat = PATTERN (insn); + process_cfa_offset (asm_out_file, pat, unwind); + handled_one = true; + break; - default: - gcc_unreachable (); - } - } + case REG_CFA_REGISTER: + pat = XEXP (note, 0); + if (pat == NULL) + pat = PATTERN (insn); + process_cfa_register (asm_out_file, pat, unwind); + handled_one = true; + break; + + case REG_FRAME_RELATED_EXPR: + case REG_CFA_DEF_CFA: + case REG_CFA_EXPRESSION: + case REG_CFA_RESTORE: + case REG_CFA_SET_VDRAP: + /* Not used in the ia64 port. */ + gcc_unreachable (); + + default: + /* Not a frame-related note. */ + break; + } + + /* All REG_FRAME_RELATED_P insns, besides ALLOC, are marked with the + explicit action to take. No guessing required. */ + gcc_assert (handled_one); } /* Implement TARGET_ASM_EMIT_EXCEPT_PERSONALITY. */ diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index b81a8b939e5..ce58827de3e 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -46,11 +46,6 @@ #include "target-def.h" #include "df.h" -/* Maximum size we are allowed to grow the stack in a single operation. - If we want more, we must do it in increments of at most this size. - If this value is 0, we don't check at all. */ -int mcore_stack_increment = STACK_UNITS_MAXSTEP; - /* For dumping information about frame sizes. */ char * mcore_current_function_name = 0; long mcore_current_compilation_timestamp = 0; diff --git a/gcc/config/mcore/mcore.opt b/gcc/config/mcore/mcore.opt index c445237301a..8e465d3a08c 100644 --- a/gcc/config/mcore/mcore.opt +++ b/gcc/config/mcore/mcore.opt @@ -63,8 +63,11 @@ mslow-bytes Target Report Mask(SLOW_BYTES) Prefer word accesses over byte accesses +; Maximum size we are allowed to grow the stack in a single operation. +; If we want more, we must do it in increments of at most this size. +; If this value is 0, we don't check at all. mstack-increment= -Target RejectNegative Joined UInteger Var(mcore_stack_increment) VarExists +Target RejectNegative Joined UInteger Var(mcore_stack_increment) Init(STACK_UNITS_MAXSTEP) Set the maximum amount for a single stack increment operation mwide-bitfields diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index d26990e593b..56e4f2da16f 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -13025,6 +13025,10 @@ static const struct mips_builtin_description mips_builtins[] = { DIRECT_NO_TARGET_BUILTIN (cache, MIPS_VOID_FTYPE_SI_CVPOINTER, cache) }; +/* Index I is the function declaration for mips_builtins[I], or null if the + function isn't defined on this target. */ +static GTY(()) tree mips_builtin_decls[ARRAY_SIZE (mips_builtins)]; + /* MODE is a vector mode whose elements have type TYPE. Return the type of the vector itself. */ @@ -13141,12 +13145,23 @@ mips_init_builtins (void) { d = &mips_builtins[i]; if (d->avail ()) - add_builtin_function (d->name, - mips_build_function_type (d->function_type), - i, BUILT_IN_MD, NULL, NULL); + mips_builtin_decls[i] + = add_builtin_function (d->name, + mips_build_function_type (d->function_type), + i, BUILT_IN_MD, NULL, NULL); } } +/* Implement TARGET_BUILTIN_DECL. */ + +static tree +mips_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED) +{ + if (code >= ARRAY_SIZE (mips_builtins)) + return error_mark_node; + return mips_builtin_decls[code]; +} + /* Take argument ARGNO from EXP's argument list and convert it into a form suitable for input operand OPNO of instruction ICODE. Return the value. */ @@ -16519,6 +16534,8 @@ mips_shift_truncation_mask (enum machine_mode mode) #undef TARGET_INIT_BUILTINS #define TARGET_INIT_BUILTINS mips_init_builtins +#undef TARGET_BUILTIN_DECL +#define TARGET_BUILTIN_DECL mips_builtin_decl #undef TARGET_EXPAND_BUILTIN #define TARGET_EXPAND_BUILTIN mips_expand_builtin diff --git a/gcc/config/picochip/picochip.md b/gcc/config/picochip/picochip.md index 6186eaa880b..b274c1ac77e 100644 --- a/gcc/config/picochip/picochip.md +++ b/gcc/config/picochip/picochip.md @@ -622,7 +622,7 @@ ; Match a branch instruction, created from a tstport/cbranch split. ; We use a "use" clause so GCC doesnt try to use this pattern generally. -(define_insn "*branch" +(define_insn "branch" [(set (pc) (if_then_else (match_operator 2 "comparison_operator" @@ -2511,22 +2511,38 @@ ;;============================================================================ ;; Define expand seems to consider the resulting two instructions to be -;; independent. It was moving the actual copy instruction further down -;; with a call instruction in between. The call was clobbering the CC -;; and hence the cond_copy was wrong. With a split, it works correctly. +;; independent. With a split, guarded by reload, it works correctly. (define_expand "movhicc" - [(set (reg:CC CC_REGNUM) (match_operand 1 "comparison_operator" "")) - (parallel [(set (match_operand:HI 0 "register_operand" "=r,r") - (if_then_else:HI (match_op_dup:HI 1 [(reg:CC CC_REGNUM) (const_int 0)]) - (match_operand:HI 2 "picochip_register_or_immediate_operand" "0,0") - (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i"))) - (use (match_dup 4))])] + [(set (match_operand:HI 0 "register_operand" "=r,r") + (if_then_else:HI (match_operand:HI 1 "" "") + (match_operand:HI 2 "register_operand" "0,0") + (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i")))] "" {if (!picochip_check_conditional_copy (operands)) FAIL; operands[4] = GEN_INT(GET_CODE(operands[1])); }) +(define_insn_and_split "*checked_movhicc" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (if_then_else:HI (match_operator 1 "picochip_peephole_comparison_operator" + [(match_operand:HI 4 "register_operand" "r,r") + (match_operand:HI 5 "picochip_comparison_operand" "r,i")]) + (match_operand:HI 2 "register_operand" "0,0") + (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i")))] + "" + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) (match_dup 1)) + (parallel [(set (match_operand:HI 0 "register_operand" "=r,r") + (if_then_else:HI (match_op_dup:HI 1 [(reg:CC CC_REGNUM) (const_int 0)]) + (match_operand:HI 2 "picochip_register_or_immediate_operand" "0,0") + (match_operand:HI 3 "picochip_register_or_immediate_operand" "r,i"))) + (use (match_dup 6))])] + "{ + operands[6] = GEN_INT(GET_CODE(operands[0])); + }") + ;; We dont do any checks here. But this pattern is used only when movhicc ;; was checked. Put a "use" clause to make sure. (define_insn "*conditional_copy" @@ -2534,7 +2550,7 @@ (if_then_else:HI (match_operator:HI 4 "picochip_peephole_comparison_operator" [(reg:CC CC_REGNUM) (const_int 0)]) - (match_operand:HI 1 "picochip_register_or_immediate_operand" "0,0") + (match_operand:HI 1 "register_operand" "0,0") (match_operand:HI 2 "picochip_register_or_immediate_operand" "r,i"))) (use (match_operand:HI 3 "const_int_operand" ""))] "" diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index c18899448ee..a5e055ed3cf 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -87,7 +87,6 @@ extern int extract_ME (rtx); extern void rs6000_output_function_entry (FILE *, const char *); extern void print_operand (FILE *, rtx, int); extern void print_operand_address (FILE *, rtx); -extern bool rs6000_output_addr_const_extra (FILE *, rtx); extern enum rtx_code rs6000_reverse_condition (enum machine_mode, enum rtx_code); extern void rs6000_emit_sISEL (enum machine_mode, rtx[]); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 4b874399ac7..5a3e333ffbe 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -996,6 +996,7 @@ static tree rs6000_builtin_vectorized_libmass (tree, tree, tree); static tree rs6000_builtin_vectorized_function (tree, tree, tree); static int rs6000_savres_strategy (rs6000_stack_t *, bool, int, int); static void rs6000_restore_saved_cr (rtx, int); +static bool rs6000_output_addr_const_extra (FILE *, rtx); static void rs6000_output_function_prologue (FILE *, HOST_WIDE_INT); static void rs6000_output_function_epilogue (FILE *, HOST_WIDE_INT); static void rs6000_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, @@ -1432,6 +1433,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_ASM_FUNCTION_EPILOGUE #define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue +#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA +#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA rs6000_output_addr_const_extra + #undef TARGET_LEGITIMIZE_ADDRESS #define TARGET_LEGITIMIZE_ADDRESS rs6000_legitimize_address @@ -5485,7 +5489,7 @@ virtual_stack_registers_memory_p (rtx op) return false; return (regnum >= FIRST_VIRTUAL_REGISTER - && regnum <= LAST_VIRTUAL_REGISTER); + && regnum <= LAST_VIRTUAL_POINTER_REGISTER); } static bool @@ -7028,46 +7032,6 @@ rs6000_eliminate_indexed_memrefs (rtx operands[2]) copy_addr_to_reg (XEXP (operands[1], 0))); } -/* Return true if OP, a SYMBOL_REF, should be considered local when - generating -mcmodel=medium code. */ - -static bool -toc_relative_ok (rtx op) -{ - tree decl; - - if (!SYMBOL_REF_LOCAL_P (op)) - return false; - - /* This is a bit hard to explain. When building shared libraries, - you are supposed to pass -fpic or -fPIC to the compiler. - -fpic/-fPIC not only generate position independent code but also - generate code that supports ELF shared library global function - or variable overriding. ppc64 is always PIC and at least some of - the ELF shared libaray semantics of global variables happen to be - supported without -fpic/-fPIC. So people may not be careful - about using -fPIC for shared libs. - With -mcmodel=medium this situation changes. A shared library - built without -fpic/-fPIC requires text relocs for global var - access (and would fail to load since glibc ld.so doesn't support - the required dynamic relocs). So avoid this potential - problem by using -mcmodel=large access for global vars, unless - we know we are compiling for an executable. */ - if (flag_pie) - return true; - - decl = SYMBOL_REF_DECL (op); - if (!decl || !DECL_P (decl)) - return true; - if (!TREE_PUBLIC (decl)) - return true; - if (DECL_VISIBILITY (decl) != VISIBILITY_DEFAULT) - return true; - - /* If we get here we must have a global var. See binds_local_p. */ - return flag_whole_program; -} - /* Return true if memory accesses to DECL are known to never straddle a 32k boundary. */ @@ -7423,7 +7387,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) || (TARGET_CMODEL == CMODEL_MEDIUM && GET_CODE (operands[1]) == SYMBOL_REF && !CONSTANT_POOL_ADDRESS_P (operands[1]) - && toc_relative_ok (operands[1]) + && SYMBOL_REF_LOCAL_P (operands[1]) && offsettable_ok_by_alignment (SYMBOL_REF_DECL (operands[1])))) { rtx reg = NULL_RTX; @@ -16026,9 +15990,9 @@ print_operand_address (FILE *file, rtx x) gcc_unreachable (); } -/* Implement OUTPUT_ADDR_CONST_EXTRA for address X. */ +/* Implement TARGET_OUTPUT_ADDR_CONST_EXTRA. */ -bool +static bool rs6000_output_addr_const_extra (FILE *file, rtx x) { if (GET_CODE (x) == UNSPEC) diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index b12ed819ab8..24edf6cb98c 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2411,12 +2411,6 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */ #define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) -#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \ - do \ - if (!rs6000_output_addr_const_extra (STREAM, X)) \ - goto FAIL; \ - while (0) - /* uncomment for disabling the corresponding default options */ /* #define MACHINE_no_sched_interblock */ /* #define MACHINE_no_sched_speculative */ diff --git a/gcc/config/rs6000/vxworks.h b/gcc/config/rs6000/vxworks.h index c1198141088..1b23835959f 100644 --- a/gcc/config/rs6000/vxworks.h +++ b/gcc/config/rs6000/vxworks.h @@ -44,7 +44,9 @@ along with GCC; see the file COPYING3. If not see \ /* C89 namespace violation! */ \ builtin_define ("CPU_FAMILY=PPC"); \ - } \ + \ + VXWORKS_OS_CPP_BUILTINS (); \ + } \ while (0) /* Only big endian PPC is supported by VxWorks. */ diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index 22992732c9a..a932eb5bef0 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -1905,7 +1905,7 @@ rx_expand_builtin_mvtipl (rtx arg) if (rx_cpu_type == RX610) return NULL_RTX; - if (! CONST_INT_P (arg) || ! IN_RANGE (arg, 0, (1 << 4) - 1)) + if (! CONST_INT_P (arg) || ! IN_RANGE (INTVAL (arg), 0, (1 << 4) - 1)) return NULL_RTX; emit_insn (gen_mvtipl (arg)); @@ -1974,6 +1974,31 @@ rx_expand_builtin_round (rtx arg, rtx target) return target; } +static int +valid_psw_flag (rtx op, char *which) +{ + static int mvtc_inform_done = 0; + + if (GET_CODE (op) == CONST_INT) + switch (INTVAL (op)) + { + case 0: case 'c': case 'C': + case 1: case 'z': case 'Z': + case 2: case 's': case 'S': + case 3: case 'o': case 'O': + case 8: case 'i': case 'I': + case 9: case 'u': case 'U': + return 1; + } + + error ("__builtin_rx_%s takes 'C', 'Z', 'S', 'O', 'I', or 'U'", which); + if (!mvtc_inform_done) + error ("use __builtin_rx_mvtc (0, ... ) to write arbitrary values to PSW"); + mvtc_inform_done = 1; + + return 0; +} + static rtx rx_expand_builtin (tree exp, rtx target, @@ -1989,10 +2014,14 @@ rx_expand_builtin (tree exp, switch (fcode) { case RX_BUILTIN_BRK: emit_insn (gen_brk ()); return NULL_RTX; - case RX_BUILTIN_CLRPSW: return rx_expand_void_builtin_1_arg - (op, gen_clrpsw, false); - case RX_BUILTIN_SETPSW: return rx_expand_void_builtin_1_arg - (op, gen_setpsw, false); + case RX_BUILTIN_CLRPSW: + if (!valid_psw_flag (op, "clrpsw")) + return NULL_RTX; + return rx_expand_void_builtin_1_arg (op, gen_clrpsw, false); + case RX_BUILTIN_SETPSW: + if (!valid_psw_flag (op, "setpsw")) + return NULL_RTX; + return rx_expand_void_builtin_1_arg (op, gen_setpsw, false); case RX_BUILTIN_INT: return rx_expand_void_builtin_1_arg (op, gen_int, false); case RX_BUILTIN_MACHI: return rx_expand_builtin_mac (exp, gen_machi); diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 0ad53637596..e0271d66322 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -1369,7 +1369,7 @@ ) (define_insn "bitclr" - [(set:SI (match_operand:SI 0 "register_operand" "+r") + [(set:SI (match_operand:SI 0 "register_operand" "=r") (and:SI (match_operand:SI 1 "register_operand" "0") (not:SI (ashift:SI (const_int 1) (match_operand:SI 2 "nonmemory_operand" "ri")))))] @@ -1379,7 +1379,7 @@ ) (define_insn "bitclr_in_memory" - [(set:QI (match_operand:QI 0 "memory_operand" "+m") + [(set:QI (match_operand:QI 0 "memory_operand" "=m") (and:QI (match_operand:QI 1 "memory_operand" "0") (not:QI (ashift:QI (const_int 1) (match_operand:QI 2 "nonmemory_operand" "ri")))))] @@ -1803,7 +1803,7 @@ ;; Clear Processor Status Word (define_insn "clrpsw" - [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i")] + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_BUILTIN_CLRPSW) (clobber (reg:CC CC_REG))] "" @@ -1813,7 +1813,7 @@ ;; Set Processor Status Word (define_insn "setpsw" - [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i")] + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_BUILTIN_SETPSW) (clobber (reg:CC CC_REG))] "" @@ -1824,7 +1824,7 @@ ;; Move from control register (define_insn "mvfc" [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")] + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_BUILTIN_MVFC))] "" "mvfc\t%C1, %0" @@ -1833,7 +1833,7 @@ ;; Move to control register (define_insn "mvtc" - [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i,i") + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i") (match_operand:SI 1 "nonmemory_operand" "r,i")] UNSPEC_BUILTIN_MVTC)] "" @@ -1848,7 +1848,7 @@ ;; Move to interrupt priority level (define_insn "mvtipl" - [(unspec:SI [(match_operand:SI 0 "immediate_operand" "Uint04")] + [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "Uint04")] UNSPEC_BUILTIN_MVTIPL)] "" "mvtipl\t%0" diff --git a/gcc/config/sparc/constraints.md b/gcc/config/sparc/constraints.md index ee0fbbda69a..73c4087d904 100644 --- a/gcc/config/sparc/constraints.md +++ b/gcc/config/sparc/constraints.md @@ -35,10 +35,10 @@ ;; In the non-V9 case, coerce V9 'e' class to 'f', so we can use 'e' in the ;; MD file for V8 and V9. -(define_register_constraint "e" "TARGET_V9 ? EXTRA_FP_REGS : FP_REGS" +(define_register_constraint "e" "(TARGET_FPU ? (TARGET_V9 ? EXTRA_FP_REGS : FP_REGS) : NO_REGS)" "Any floating-point register") -(define_register_constraint "f" "FP_REGS" +(define_register_constraint "f" "(TARGET_FPU ? FP_REGS : NO_REGS)" "Lower floating-point register") (define_register_constraint "h" "(TARGET_V9 && TARGET_V8PLUS ? I64_REGS : NO_REGS)" diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h index 530a6ae7065..1272d2aba7d 100644 --- a/gcc/config/sparc/linux.h +++ b/gcc/config/sparc/linux.h @@ -107,7 +107,8 @@ along with GCC; see the file COPYING3. If not see %{Ym,*} \ %{Wa,*:%*} \ -s \ -%{fpic|fPIC|fpie|fPIE|findirect-dispatch:-K PIC} \ +%{fpic|fPIC|fpie|fPIE:-K PIC} \ +%{!.c:%{findirect-dispatch:-K PIC}} \ %(asm_cpu) %(asm_relax)" #undef ASM_OUTPUT_ALIGNED_LOCAL diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h index 369c13c8e3c..d8a242758dd 100644 --- a/gcc/config/sparc/linux64.h +++ b/gcc/config/sparc/linux64.h @@ -236,7 +236,8 @@ along with GCC; see the file COPYING3. If not see %{Ym,*} \ %{Wa,*:%*} \ -s \ -%{fpic|fPIC|fpie|fPIE|findirect-dispatch:-K PIC} \ +%{fpic|fPIC|fpie|fPIE:-K PIC} \ +%{!.c:%{findirect-dispatch:-K PIC}} \ %{mlittle-endian:-EL} \ %(asm_cpu) %(asm_arch) %(asm_relax)" diff --git a/gcc/config/t-darwin b/gcc/config/t-darwin index b538ccfa405..70c0da54bbc 100644 --- a/gcc/config/t-darwin +++ b/gcc/config/t-darwin @@ -36,7 +36,7 @@ darwin-f.o: $(srcdir)/config/darwin-f.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(srcdir)/config/darwin-f.c $(PREPROCESSOR_DEFINES) darwin-driver.o: $(srcdir)/config/darwin-driver.c \ - $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) + $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) opts.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ $(srcdir)/config/darwin-driver.c diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index 49b8e756e92..dc047a2056c 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -48,49 +48,12 @@ #define streq(a,b) (strcmp (a, b) == 0) #endif -/* Function prototypes for stupid compilers: */ -static bool v850_handle_option (size_t, const char *, int); -static void v850_option_optimization (int, int); -static void const_double_split (rtx, HOST_WIDE_INT *, HOST_WIDE_INT *); -static int const_costs_int (HOST_WIDE_INT, int); -static int const_costs (rtx, enum rtx_code); -static bool v850_rtx_costs (rtx, int, int, int *, bool); -static void substitute_ep_register (rtx, rtx, int, int, rtx *, rtx *); -static void v850_reorg (void); -static int ep_memory_offset (enum machine_mode, int); -static void v850_set_data_area (tree, v850_data_area); -static tree v850_handle_interrupt_attribute (tree *, tree, tree, int, bool *); -static tree v850_handle_data_area_attribute (tree *, tree, tree, int, bool *); -static void v850_insert_attributes (tree, tree *); -static void v850_asm_init_sections (void); -static section *v850_select_section (tree, int, unsigned HOST_WIDE_INT); -static void v850_encode_data_area (tree, rtx); -static void v850_encode_section_info (tree, rtx, int); -static int v850_issue_rate (void); -static bool v850_return_in_memory (const_tree, const_tree); -static rtx v850_function_value (const_tree, const_tree, bool); -static void v850_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, - tree, int *, int); -static bool v850_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, - const_tree, bool); -static int v850_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, - tree, bool); -static bool v850_strict_argument_naming (CUMULATIVE_ARGS *); -static rtx v850_function_arg (CUMULATIVE_ARGS *, enum machine_mode, - const_tree, bool); -static void v850_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, - const_tree, bool); -static bool v850_can_eliminate (const int, const int); -static void v850_asm_trampoline_template (FILE *); -static void v850_trampoline_init (rtx, tree, rtx); -static void v850_print_operand (FILE *, rtx, int); static void v850_print_operand_address (FILE *, rtx); -static bool v850_print_operand_punct_valid_p (unsigned char code); /* Information about the various small memory areas. */ struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] = { - /* name max physical max */ + /* Name Max Physical max. */ { "tda", 0, 256 }, { "sda", 0, 65536 }, { "zda", 0, 32768 }, @@ -113,116 +76,11 @@ rtx v850_compare_op0, v850_compare_op1; /* Whether current function is an interrupt handler. */ static int v850_interrupt_p = FALSE; -static GTY(()) section *rosdata_section; -static GTY(()) section *rozdata_section; -static GTY(()) section *tdata_section; -static GTY(()) section *zdata_section; -static GTY(()) section *zbss_section; - -/* V850 specific attributes. */ - -static const struct attribute_spec v850_attribute_table[] = -{ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ - { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute }, - { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute }, - { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute }, - { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute }, - { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute }, - { NULL, 0, 0, false, false, false, NULL } -}; - - -/* Initialize the GCC target structure. */ -#undef TARGET_ASM_ALIGNED_HI_OP -#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" - -#undef TARGET_PRINT_OPERAND -#define TARGET_PRINT_OPERAND v850_print_operand -#undef TARGET_PRINT_OPERAND_ADDRESS -#define TARGET_PRINT_OPERAND_ADDRESS v850_print_operand_address -#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P -#define TARGET_PRINT_OPERAND_PUNCT_VALID_P v850_print_operand_punct_valid_p - -#undef TARGET_ATTRIBUTE_TABLE -#define TARGET_ATTRIBUTE_TABLE v850_attribute_table - -#undef TARGET_INSERT_ATTRIBUTES -#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes - -#undef TARGET_ASM_SELECT_SECTION -#define TARGET_ASM_SELECT_SECTION v850_select_section - -/* The assembler supports switchable .bss sections, but - v850_select_section doesn't yet make use of them. */ -#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS -#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false - -#undef TARGET_ENCODE_SECTION_INFO -#define TARGET_ENCODE_SECTION_INFO v850_encode_section_info - -#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE -#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true - -#undef TARGET_DEFAULT_TARGET_FLAGS -#define TARGET_DEFAULT_TARGET_FLAGS (MASK_DEFAULT | MASK_APP_REGS) -#undef TARGET_HANDLE_OPTION -#define TARGET_HANDLE_OPTION v850_handle_option - -#undef TARGET_RTX_COSTS -#define TARGET_RTX_COSTS v850_rtx_costs - -#undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST hook_int_rtx_bool_0 - -#undef TARGET_MACHINE_DEPENDENT_REORG -#define TARGET_MACHINE_DEPENDENT_REORG v850_reorg - -#undef TARGET_SCHED_ISSUE_RATE -#define TARGET_SCHED_ISSUE_RATE v850_issue_rate - -#undef TARGET_PROMOTE_PROTOTYPES -#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true - -#undef TARGET_RETURN_IN_MEMORY -#define TARGET_RETURN_IN_MEMORY v850_return_in_memory - -#undef TARGET_FUNCTION_VALUE -#define TARGET_FUNCTION_VALUE v850_function_value - -#undef TARGET_PASS_BY_REFERENCE -#define TARGET_PASS_BY_REFERENCE v850_pass_by_reference - -#undef TARGET_CALLEE_COPIES -#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true - -#undef TARGET_SETUP_INCOMING_VARARGS -#define TARGET_SETUP_INCOMING_VARARGS v850_setup_incoming_varargs - -#undef TARGET_ARG_PARTIAL_BYTES -#define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes - -#undef TARGET_FUNCTION_ARG -#define TARGET_FUNCTION_ARG v850_function_arg - -#undef TARGET_FUNCTION_ARG_ADVANCE -#define TARGET_FUNCTION_ARG_ADVANCE v850_function_arg_advance - -#undef TARGET_CAN_ELIMINATE -#define TARGET_CAN_ELIMINATE v850_can_eliminate - -#undef TARGET_ASM_TRAMPOLINE_TEMPLATE -#define TARGET_ASM_TRAMPOLINE_TEMPLATE v850_asm_trampoline_template -#undef TARGET_TRAMPOLINE_INIT -#define TARGET_TRAMPOLINE_INIT v850_trampoline_init - -#undef TARGET_STRICT_ARGUMENT_NAMING -#define TARGET_STRICT_ARGUMENT_NAMING v850_strict_argument_naming - -#undef TARGET_OPTION_OPTIMIZATION -#define TARGET_OPTION_OPTIMIZATION v850_option_optimization - -struct gcc_target targetm = TARGET_INITIALIZER; +static GTY(()) section * rosdata_section; +static GTY(()) section * rozdata_section; +static GTY(()) section * tdata_section; +static GTY(()) section * zdata_section; +static GTY(()) section * zbss_section; /* Set the maximum size of small memory area TYPE to the value given by VALUE. Return true if VALUE was syntactically correct. VALUE @@ -1120,7 +978,7 @@ v850_float_nz_comparison_operator (rtx op, enum machine_mode mode) } enum machine_mode -v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1) +v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED) { if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) { @@ -2022,8 +1880,6 @@ expand_epilogue (void) && !interrupt_handler) { int alloc_stack = (4 * num_restore); - int restore_func_len; - int restore_normal_len; /* Don't bother checking if we don't actually save any space. */ if (use_prolog_function (num_restore, actual_fsize)) @@ -2222,6 +2078,9 @@ notice_update_cc (rtx body, rtx insn) /* Insn doesn't leave CC in a usable state. */ CC_STATUS_INIT; break; + + default: + break; } } @@ -3157,6 +3016,14 @@ v850_select_section (tree exp, return readonly_data_section; } +/* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */ + +static bool +v850_function_value_regno_p (const unsigned int regno) +{ + return (regno == 10); +} + /* Worker function for TARGET_RETURN_IN_MEMORY. */ static bool @@ -3168,7 +3035,7 @@ v850_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) /* Worker function for TARGET_FUNCTION_VALUE. */ -rtx +static rtx v850_function_value (const_tree valtype, const_tree fn_decl_or_type ATTRIBUTE_UNUSED, bool outgoing ATTRIBUTE_UNUSED) @@ -3233,4 +3100,111 @@ v850_issue_rate (void) { return (TARGET_V850E2_ALL? 2 : 1); } + +/* V850 specific attributes. */ + +static const struct attribute_spec v850_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ + { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute }, + { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute }, + { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute }, + { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute }, + { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute }, + { NULL, 0, 0, false, false, false, NULL } +}; + +/* Initialize the GCC target structure. */ +#undef TARGET_ASM_ALIGNED_HI_OP +#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" + +#undef TARGET_PRINT_OPERAND +#define TARGET_PRINT_OPERAND v850_print_operand +#undef TARGET_PRINT_OPERAND_ADDRESS +#define TARGET_PRINT_OPERAND_ADDRESS v850_print_operand_address +#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P +#define TARGET_PRINT_OPERAND_PUNCT_VALID_P v850_print_operand_punct_valid_p + +#undef TARGET_ATTRIBUTE_TABLE +#define TARGET_ATTRIBUTE_TABLE v850_attribute_table + +#undef TARGET_INSERT_ATTRIBUTES +#define TARGET_INSERT_ATTRIBUTES v850_insert_attributes + +#undef TARGET_ASM_SELECT_SECTION +#define TARGET_ASM_SELECT_SECTION v850_select_section + +/* The assembler supports switchable .bss sections, but + v850_select_section doesn't yet make use of them. */ +#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS +#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false + +#undef TARGET_ENCODE_SECTION_INFO +#define TARGET_ENCODE_SECTION_INFO v850_encode_section_info + +#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE +#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true + +#undef TARGET_DEFAULT_TARGET_FLAGS +#define TARGET_DEFAULT_TARGET_FLAGS (MASK_DEFAULT | MASK_APP_REGS) +#undef TARGET_HANDLE_OPTION +#define TARGET_HANDLE_OPTION v850_handle_option + +#undef TARGET_RTX_COSTS +#define TARGET_RTX_COSTS v850_rtx_costs + +#undef TARGET_ADDRESS_COST +#define TARGET_ADDRESS_COST hook_int_rtx_bool_0 + +#undef TARGET_MACHINE_DEPENDENT_REORG +#define TARGET_MACHINE_DEPENDENT_REORG v850_reorg + +#undef TARGET_SCHED_ISSUE_RATE +#define TARGET_SCHED_ISSUE_RATE v850_issue_rate + +#undef TARGET_FUNCTION_VALUE_REGNO_P +#define TARGET_FUNCTION_VALUE_REGNO_P v850_function_value_regno_p +#undef TARGET_FUNCTION_VALUE +#define TARGET_FUNCTION_VALUE v850_function_value + +#undef TARGET_PROMOTE_PROTOTYPES +#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true + +#undef TARGET_RETURN_IN_MEMORY +#define TARGET_RETURN_IN_MEMORY v850_return_in_memory + +#undef TARGET_PASS_BY_REFERENCE +#define TARGET_PASS_BY_REFERENCE v850_pass_by_reference + +#undef TARGET_CALLEE_COPIES +#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true + +#undef TARGET_SETUP_INCOMING_VARARGS +#define TARGET_SETUP_INCOMING_VARARGS v850_setup_incoming_varargs + +#undef TARGET_ARG_PARTIAL_BYTES +#define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes + +#undef TARGET_FUNCTION_ARG +#define TARGET_FUNCTION_ARG v850_function_arg + +#undef TARGET_FUNCTION_ARG_ADVANCE +#define TARGET_FUNCTION_ARG_ADVANCE v850_function_arg_advance + +#undef TARGET_CAN_ELIMINATE +#define TARGET_CAN_ELIMINATE v850_can_eliminate + +#undef TARGET_ASM_TRAMPOLINE_TEMPLATE +#define TARGET_ASM_TRAMPOLINE_TEMPLATE v850_asm_trampoline_template +#undef TARGET_TRAMPOLINE_INIT +#define TARGET_TRAMPOLINE_INIT v850_trampoline_init + +#undef TARGET_STRICT_ARGUMENT_NAMING +#define TARGET_STRICT_ARGUMENT_NAMING v850_strict_argument_naming + +#undef TARGET_OPTION_OPTIMIZATION +#define TARGET_OPTION_OPTIMIZATION v850_option_optimization + +struct gcc_target targetm = TARGET_INITIALIZER; + #include "gt-v850.h" diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h index 9ae0784af56..2afa3cb22a6 100644 --- a/gcc/config/v850/v850.h +++ b/gcc/config/v850/v850.h @@ -596,10 +596,6 @@ struct cum_arg { int nbytes; int anonymous_args; }; #define LIBCALL_VALUE(MODE) \ gen_rtx_REG (MODE, 10) -/* 1 if N is a possible register number for a function value. */ - -#define FUNCTION_VALUE_REGNO_P(N) ((N) == 10) - #define DEFAULT_PCC_STRUCT_RETURN 0 /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, @@ -1071,6 +1067,10 @@ extern union tree_node * GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_K #define TARGET_ASM_INIT_SECTIONS v850_asm_init_sections -#endif /* ! GCC_V850_H */ - +/* Define this so that the cc1plus will not think that system header files + need an implicit 'extern "C" { ... }' assumed. This breaks testing C++ + in a build directory where the libstdc++ header files are found via a + -isystem <path-to-build-dir>. */ +#define NO_IMPLICIT_EXTERN_C +#endif /* ! GCC_V850_H */ diff --git a/gcc/config/vms/t-vms b/gcc/config/vms/t-vms index 132a53b205c..75756a234d9 100644 --- a/gcc/config/vms/t-vms +++ b/gcc/config/vms/t-vms @@ -24,15 +24,14 @@ LIMITS_H_TEST = false # Under VMS, directory names cannot contain dots. version:=$(shell echo $(BASEVER_c) | sed -e 's/\./_/g') -# Temporary restriction: VMS_EXTRA_PARTS must be compiled by DEC C. -#VMS_EXTRA_PARTS=vcrt0.o pcrt0.o -VMS_EXTRA_PARTS= - -DECC=`echo $(CC) | sed -e 's/xgcc -B.*/decc$(exeext)/' -e 's/^gcc/decc/' -e 's/^decc/.\/decc/' -e 's/\(.*\)-gcc/\1-decc/'` +VMS_EXTRA_PARTS=vcrt0.o pcrt0.o # Assemble startup files. -$(T)vcrt0.o: $(CRT0_S) $(GCC_PASSES) - $(DECC) -c /names=as_is $(srcdir)/config/vms/vms-crt0.c -o $(T)vcrt0.o +$(T)vcrt0.o: $(srcdir)/config/vms/vms-ucrt0.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ + -c -o $(T)vcrt0.o $(srcdir)/config/vms/vms-ucrt0.c + +$(T)pcrt0.o: $(srcdir)/config/vms/vms-ucrt0.c $(GCC_PASSES) + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \ + -c -o $(T)pcrt0.o -DCRT0_POSIX_EXIT $(srcdir)/config/vms/vms-ucrt0.c -$(T)pcrt0.o: $(CRT0_S) $(GCC_PASSES) - $(DECC) -c /names=as_is $(srcdir)/config/vms/vms-psxcrt0.c -o $(T)pcrt0.o diff --git a/gcc/config/vms/t-vms64 b/gcc/config/vms/t-vms64 deleted file mode 100644 index 2fe00692fb5..00000000000 --- a/gcc/config/vms/t-vms64 +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2009 -# 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 3, 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 COPYING3. If not see -# <http://www.gnu.org/licenses/>. - -# Assemble startup files. -$(T)vcrt0.o: $(CRT0_S) $(GCC_PASSES) - $(DECC) -c /names=as_is /pointer_size=64 \ - $(srcdir)/config/vms/vms-crt0-64.c -o $(T)vcrt0.o - -$(T)pcrt0.o: $(CRT0_S) $(GCC_PASSES) - $(DECC) -c /names=as_is /pointer_size=64 \ - $(srcdir)/config/vms/vms-psxcrt0-64.c -o $(T)pcrt0.o diff --git a/gcc/config/vms/vms-crt0-64.c b/gcc/config/vms/vms-crt0-64.c deleted file mode 100644 index ec59d81d6af..00000000000 --- a/gcc/config/vms/vms-crt0-64.c +++ /dev/null @@ -1,95 +0,0 @@ -/* VMS 64bit crt0 returning VMS style condition codes . - Copyright (C) 2001, 2009 Free Software Foundation, Inc. - Contributed by Douglas B. Rupp (rupp@gnat.com). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -#if !defined(__DECC) -You Lose! This file can only be compiled with DEC C. -#else - -/* This file can only be compiled with DEC C, due to the call to - lib$establish and the pragmas pointer_size. */ - -#pragma __pointer_size short - -#include <stdlib.h> -#include <string.h> -#include <ssdef.h> - -extern void decc$main (); - -extern int main (); - -static int -handler (sigargs, mechargs) - void *sigargs; - void *mechargs; -{ - return SS$_RESIGNAL; -} - -int -__main (arg1, arg2, arg3, image_file_desc, arg5, arg6) - void *arg1, *arg2, *arg3; - void *image_file_desc; - void *arg5, *arg6; -{ - int argc; - char **argv; - char **envp; - -#pragma __pointer_size long - - int i; - char **long_argv; - char **long_envp; - -#pragma __pointer_size short - - lib$establish (handler); - decc$main (arg1, arg2, arg3, image_file_desc, - arg5, arg6, &argc, &argv, &envp); - -#pragma __pointer_size long - - /* Reallocate argv with 64 bit pointers. */ - long_argv = (char **) _malloc32 (sizeof (char *) * (argc + 1)); - - for (i = 0; i < argc; i++) - long_argv[i] = (char *) _strdup32 (argv[i]); - - long_argv[argc] = (char *) 0; - - for (i = 0; envp[i]; i++); - long_envp = (char **) _malloc32 (sizeof (char *) * (i + 1)); - - for (i = 0; envp[i]; i++) - long_envp[i] = (char *) _strdup32 (envp[i]); - - long_envp[i] = (char *) 0; - -#pragma __pointer_size short - - return main (argc, long_argv, long_envp); -} -#endif diff --git a/gcc/config/vms/vms-crt0.c b/gcc/config/vms/vms-crt0.c deleted file mode 100644 index c0fdaaf16c6..00000000000 --- a/gcc/config/vms/vms-crt0.c +++ /dev/null @@ -1,66 +0,0 @@ -/* VMS crt0 returning VMS style condition codes . - Copyright (C) 2001, 2009 Free Software Foundation, Inc. - Contributed by Douglas B. Rupp (rupp@gnat.com). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -#if !defined(__DECC) -You Lose! This file can only be compiled with DEC C. -#else - -/* This file can only be compiled with DEC C, due to the call to - lib$establish. */ - -#include <stdlib.h> -#include <string.h> -#include <ssdef.h> - -extern void decc$main (); - -extern int main (); - -static int -handler (sigargs, mechargs) - void *sigargs; - void *mechargs; -{ - return SS$_RESIGNAL; -} - -int -__main (arg1, arg2, arg3, image_file_desc, arg5, arg6) - void *arg1, *arg2, *arg3; - void *image_file_desc; - void *arg5, *arg6; -{ - int argc; - char **argv; - char **envp; - - lib$establish (handler); - - decc$main(arg1, arg2, arg3, image_file_desc, arg5, arg6, - &argc, &argv, &envp); - - return main (argc, argv, envp); -} -#endif diff --git a/gcc/config/vms/vms-psxcrt0-64.c b/gcc/config/vms/vms-psxcrt0-64.c deleted file mode 100644 index 45afbc9a03d..00000000000 --- a/gcc/config/vms/vms-psxcrt0-64.c +++ /dev/null @@ -1,124 +0,0 @@ -/* VMS 64bit crt0 returning Unix style condition codes . - Copyright (C) 2001, 2009 Free Software Foundation, Inc. - Contributed by Douglas B. Rupp (rupp@gnat.com). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -#if !defined(__DECC) -You Lose! This file can only be compiled with DEC C. -#else - -/* This file can only be compiled with DEC C, due to the call to - lib$establish and the pragmas pointer_size. */ - -#pragma __pointer_size short - -#include <stdlib.h> -#include <string.h> -#include <ssdef.h> -#include <stsdef.h> -#include <errnodef.h> - -extern void decc$main (); -extern int main (); - -static int -handler (sigargs, mechargs) - void *sigargs; - void *mechargs; -{ - return SS$_RESIGNAL; -} - -int -__main (arg1, arg2, arg3, image_file_desc, arg5, arg6) - void *arg1, *arg2, *arg3; - void *image_file_desc; - void *arg5, *arg6; -{ - int argc; - char **argv; - char **envp; - -#pragma __pointer_size long - - int i; - char **long_argv; - char **long_envp; - int status; - -#pragma __pointer_size short - - lib$establish (handler); - decc$main (arg1, arg2, arg3, image_file_desc, - arg5, arg6, &argc, &argv, &envp); - -#pragma __pointer_size long - - /* Reallocate argv with 64 bit pointers. */ - long_argv = (char **) _malloc32 (sizeof (char *) * (argc + 1)); - - for (i = 0; i < argc; i++) - long_argv[i] = (char *) _strdup32 (argv[i]); - - long_argv[argc] = (char *) 0; - - for (i = 0; envp[i]; i++); - long_envp = (char **) _malloc32 (sizeof (char *) * (i + 1)); - - for (i = 0; envp[i]; i++) - long_envp[i] = (char *) _strdup32 (envp[i]); - - long_envp[i] = (char *) 0; - -#pragma __pointer_size short - - status = main (argc, long_argv, long_envp); - - /* Map into a range of 0 - 255. */ - status = status & 255; - - if (status > 0) - { - int save_status = status; - - status = C$_EXIT1 + ((status - 1) << STS$V_MSG_NO); - - /* An exit failure status requires a "severe" error. All status values - are defined in errno with a successful (1) severity but can be - changed to an error (2) severity by adding 1. In addition for - compatibility with UNIX exit() routines we inhibit a run-time error - message from being generated on exit(1). */ - - if (save_status == 1) - { - status++; - status |= STS$M_INHIB_MSG; - } - } - - if (status == 0) - status = SS$_NORMAL; - - return status; -} -#endif diff --git a/gcc/config/vms/vms-psxcrt0.c b/gcc/config/vms/vms-psxcrt0.c deleted file mode 100644 index 5ad5ddb0fd8..00000000000 --- a/gcc/config/vms/vms-psxcrt0.c +++ /dev/null @@ -1,94 +0,0 @@ -/* VMS crt0 returning Unix style condition codes . - Copyright (C) 2001, 2009 Free Software Foundation, Inc. - Contributed by Douglas B. Rupp (rupp@gnat.com). - - This file is part of GCC. - - GCC is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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. - - Under Section 7 of GPL version 3, you are granted additional - permissions described in the GCC Runtime Library Exception, version - 3.1, as published by the Free Software Foundation. - - You should have received a copy of the GNU General Public License and - a copy of the GCC Runtime Library Exception along with this program; - see the files COPYING3 and COPYING.RUNTIME respectively. If not, see - <http://www.gnu.org/licenses/>. */ - -#if !defined(__DECC) -You Lose! This file can only be compiled with DEC C. -#else - -/* This file can only be compiled with DEC C, due to the call to - lib$establish. */ - -#include <stdlib.h> -#include <string.h> -#include <ssdef.h> -#include <stsdef.h> -#include <errnodef.h> - -extern void decc$main (); -extern int main (); - -static int -handler (sigargs, mechargs) - void *sigargs; - void *mechargs; -{ - return SS$_RESIGNAL; -} - -int -__main (arg1, arg2, arg3, image_file_desc, arg5, arg6) - void *arg1, *arg2, *arg3; - void *image_file_desc; - void *arg5, *arg6; -{ - int argc; - char **argv; - char **envp; - int status; - - lib$establish (handler); - decc$main (arg1, arg2, arg3, image_file_desc, arg5, arg6, - &argc, &argv, &envp); - - status = main (argc, argv, envp); - - /* Map into a range of 0 - 255. */ - status = status & 255; - - if (status > 0) - { - int save_status = status; - - status = C$_EXIT1 + ((status - 1) << STS$V_MSG_NO); - - /* An exit failure status requires a "severe" error - All status values are defined in errno with a successful - (1) severity but can be changed to an error (2) severity by adding 1. - In addition for compatibility with UNIX exit() routines we inhibit - a run-time error message from being generated on exit(1). */ - - if (save_status == 1) - { - status++; - status |= STS$M_INHIB_MSG; - } - } - - if (status == 0) - status = SS$_NORMAL; - - return status; -} -#endif diff --git a/gcc/config/vms/vms-ucrt0.c b/gcc/config/vms/vms-ucrt0.c new file mode 100644 index 00000000000..344b59520e0 --- /dev/null +++ b/gcc/config/vms/vms-ucrt0.c @@ -0,0 +1,127 @@ +/* VMS crt0 returning Unix style condition codes. + Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc. + Contributed by Douglas B. Rupp (rupp@gnat.com). + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, 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. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> + +/* Lots of cheat to handle 32bits/64bits pointer conversions. + We use 'long long' for 64 bits pointers and 'int' for 32 bits pointers. */ + +extern void decc$main (void *arg1, void *arg2, void *arg3, + void *image_file_desc, void *arg5, void *arg6, + int *, int *, int *); +extern int main (int, char **, char **); +extern int _malloc32 (int); + +#ifdef __ia64__ +#define MAIN_ASM_NAME asm ("ELF$TFRADR") +#else +#define MAIN_ASM_NAME +#endif + +int __main (void *arg1, void *arg2, void *arg3, + void *image_file_desc, void *arg5, void *arg6) MAIN_ASM_NAME; + +/* From errnodef.h, but we need to emulate the globalval. */ +extern int C$_EXIT1; + +/* From stsdef.h */ +#define STS$V_MSG_NO 0x03 +#define STS$M_INHIB_MSG 0x10000000 + +/* From ssdef.h */ +#define SS$_NORMAL 1 + +int +__main (void *arg1, void *arg2, void *arg3, + void *image_file_desc, void *arg5, void *arg6) +{ + int argc; + int argv; + int envp; + int status; + int i; + long long *long_argv; + long long *long_envp; + + /* The argv and envp arrays are 32 bits pointers to 32 bits pointers. */ + decc$main (arg1, arg2, arg3, image_file_desc, + arg5, arg6, &argc, &argv, &envp); + + if (sizeof (void *) == 8) + { + /* Reallocate argv and envp with 64 bit pointers. */ + long_argv = (long long *) + (long long) _malloc32 (sizeof (long long) * (argc + 1)); + + for (i = 0; i < argc; i++) + long_argv[i] = ((int *) (long long) argv)[i]; + + long_argv[argc] = 0; + + for (i = 0; ((int *) (long long) envp)[i]; i++) + ; + long_envp = (long long *) + (long long) _malloc32 (sizeof (long long) * (i + 1)); + + for (i = 0; ((int *) (long long) envp)[i]; i++) + long_envp[i] = ((int *) (long long) envp)[i]; + + long_envp[i] = 0; + } + else + { + long_argv = (long long *) argv; + long_envp = (long long *) envp; + } + status = main (argc, (char **)long_argv, (char **)long_envp); + +#ifdef CRT0_POSIX_EXIT + /* Map into a range of 0 - 255. */ + status = status & 255; + + if (status > 0) + { + int save_status = status; + + status = (long) &C$_EXIT1 + ((status - 1) << STS$V_MSG_NO); + + /* An exit failure status requires a "severe" error. All status values + are defined in errno with a successful (1) severity but can be + changed to an error (2) severity by adding 1. In addition for + compatibility with UNIX exit() routines we inhibit a run-time error + message from being generated on exit(1). */ + + if (save_status == 1) + { + status++; + status |= STS$M_INHIB_MSG; + } + } + else + status = SS$_NORMAL; +#endif /* CRT0_POSIX_EXIT */ + + return status; +} diff --git a/gcc/configure b/gcc/configure index d9355dba12b..a97e6d79b76 100755 --- a/gcc/configure +++ b/gcc/configure @@ -759,7 +759,6 @@ SET_MAKE REPORT_BUGS_TEXI REPORT_BUGS_TO PKGVERSION -onestep CONFIGURE_SPECS CROSS_SYSTEM_HEADER_DIR TARGET_SYSTEM_ROOT_DEFINE @@ -885,7 +884,6 @@ enable_shared with_build_sysroot with_sysroot with_specs -enable_intermodule with_pkgversion with_bugurl enable_languages @@ -1588,7 +1586,6 @@ Optional Features: --enable-objc-gc enable the use of Boehm's garbage collector with the GNU Objective-C runtime --disable-shared don't provide a shared libgcc - --enable-intermodule build the compiler in one step --enable-languages=LIST specify which front-ends to build --disable-rpath do not hardcode runtime library paths --enable-initfini-array use .init_array/.fini_array sections @@ -6886,19 +6883,6 @@ fi -# Build with intermodule optimisations -# Check whether --enable-intermodule was given. -if test "${enable_intermodule+set}" = set; then : - enableval=$enable_intermodule; case ${enable_intermodule} in - yes) onestep="-onestep";; - *) onestep="";; -esac -else - onestep="" -fi - - - # Check whether --with-pkgversion was given. @@ -17139,7 +17123,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 17142 "configure" +#line 17126 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -17245,7 +17229,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 17248 "configure" +#line 17232 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -21678,12 +21662,14 @@ else gcc_cv_as_cfi_advance_working=no fi + cat >>confdefs.h <<_ACEOF #define HAVE_GAS_CFI_DIRECTIVE `if test $gcc_cv_as_cfi_directive = yes \ && test $gcc_cv_as_cfi_advance_working = yes; then echo 1; else echo 0; fi` _ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for cfi personality directive" >&5 $as_echo_n "checking assembler for cfi personality directive... " >&6; } if test "${gcc_cv_as_cfi_personality_directive+set}" = set; then : @@ -21765,6 +21751,7 @@ fi $as_echo "$gcc_cv_as_cfi_sections_directive" >&6; } + cat >>confdefs.h <<_ACEOF #define HAVE_GAS_CFI_SECTIONS_DIRECTIVE `if test $gcc_cv_as_cfi_sections_directive = yes; then echo 1; else echo 0; fi` diff --git a/gcc/configure.ac b/gcc/configure.ac index 8dd3290bccb..e8f685af182 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -754,16 +754,6 @@ AC_ARG_WITH(specs, ) AC_SUBST(CONFIGURE_SPECS) -# Build with intermodule optimisations -AC_ARG_ENABLE(intermodule, -[ --enable-intermodule build the compiler in one step], -[case ${enable_intermodule} in - yes) onestep="-onestep";; - *) onestep="";; -esac], -[onestep=""]) -AC_SUBST(onestep) - ACX_PKGVERSION([GCC]) ACX_BUGURL([http://gcc.gnu.org/bugs.html]) @@ -2398,11 +2388,13 @@ else # no objdump, err on the side of caution gcc_cv_as_cfi_advance_working=no fi +GCC_TARGET_TEMPLATE(HAVE_GAS_CFI_DIRECTIVE) AC_DEFINE_UNQUOTED(HAVE_GAS_CFI_DIRECTIVE, [`if test $gcc_cv_as_cfi_directive = yes \ && test $gcc_cv_as_cfi_advance_working = yes; then echo 1; else echo 0; fi`], [Define 0/1 if your assembler supports CFI directives.]) +GCC_TARGET_TEMPLATE(HAVE_GAS_CFI_PERSONALITY_DIRECTIVE) gcc_GAS_CHECK_FEATURE([cfi personality directive], gcc_cv_as_cfi_personality_directive, ,, [ .text @@ -2436,6 +2428,7 @@ gcc_GAS_CHECK_FEATURE([cfi sections directive], gcc_cv_as_cfi_sections_directive=yes ;; esac]) +GCC_TARGET_TEMPLATE(HAVE_GAS_CFI_SECTIONS_DIRECTIVE) AC_DEFINE_UNQUOTED(HAVE_GAS_CFI_SECTIONS_DIRECTIVE, [`if test $gcc_cv_as_cfi_sections_directive = yes; then echo 1; else echo 0; fi`], diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c412f0c9ece..4b6eb74fe8d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,34 @@ +2010-09-24 Jan Hubicka <jh@suse.cz> + + * decl.c (finish_function): Use decl_replaceable_p + * method.c (make_alias_for_thunk): Update call of cgraph_same_body_alias. + +2010-09-24 Jason Merrill <jason@redhat.com> + + * decl.c (compute_array_index_type): Remember type dependence of + array bound. + * pt.c (dependent_type_p_r): Don't recompute it here. + + * error.c (dump_expr) [CASE_CONVERT]: Print conversion between + reference and pointer to the same type as "*" or "&". + +2010-09-24 Nicola Pero <nicola.pero@meta-innovation.com> + + * typeck.c (warn_args_num): Use warning 'too many arguments to + method [methodname]' for an Objective-C method instead of the less + satisfactory 'too many arguments to function' (with no method + name). + +2010-09-21 Jason Merrill <jason@redhat.com> + + * mangle.c (write_expression) [SCOPE_REF]: Only do -fabi-version=1 + special handling if we know the member. + +2010-09-18 Jason Merrill <jason@redhat.com> + + * call.c (compare_ics): Do lvalue/rvalue reference binding + comparison for ck_list, too. + 2010-09-15 Jason Merrill <jason@redhat.com> * semantics.c (finish_id_expression): Diagnose use of function diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 2b9b848a730..89ab75723f4 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6859,9 +6859,8 @@ compare_ics (conversion *ics1, conversion *ics2) /* We couldn't make up our minds; try to figure it out below. */ } - if (ics1->ellipsis_p || ics1->kind == ck_list) - /* Both conversions are ellipsis conversions or both are building a - std::initializer_list. */ + if (ics1->ellipsis_p) + /* Both conversions are ellipsis conversions. */ return 0; /* User-defined conversion sequence U1 is a better conversion sequence @@ -6870,16 +6869,24 @@ compare_ics (conversion *ics1, conversion *ics2) ond standard conversion sequence of U1 is better than the second standard conversion sequence of U2. */ - if (ics1->user_conv_p) + /* Handle list-conversion with the same code even though it isn't always + ranked as a user-defined conversion and it doesn't have a second + standard conversion sequence; it will still have the desired effect. + Specifically, we need to do the reference binding comparison at the + end of this function. */ + + if (ics1->user_conv_p || ics1->kind == ck_list) { conversion *t1; conversion *t2; for (t1 = ics1; t1->kind != ck_user; t1 = t1->u.next) - if (t1->kind == ck_ambig || t1->kind == ck_aggr) + if (t1->kind == ck_ambig || t1->kind == ck_aggr + || t1->kind == ck_list) break; for (t2 = ics2; t2->kind != ck_user; t2 = t2->u.next) - if (t2->kind == ck_ambig || t2->kind == ck_aggr) + if (t2->kind == ck_ambig || t2->kind == ck_aggr + || t2->kind == ck_list) break; if (t1->kind != t2->kind) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 3d1420a23eb..07eddb551df 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7402,11 +7402,15 @@ compute_array_index_type (tree name, tree size) type = TREE_TYPE (size); } + /* A type is dependent if it is...an array type constructed from any + dependent type or whose size is specified by a constant expression + that is value-dependent. */ /* We can only call value_dependent_expression_p on integral constant expressions; the parser adds a dummy NOP_EXPR with TREE_SIDE_EFFECTS set if this isn't one. */ if (processing_template_decl - && (TREE_SIDE_EFFECTS (size) || value_dependent_expression_p (size))) + && (dependent_type_p (type) + || TREE_SIDE_EFFECTS (size) || value_dependent_expression_p (size))) { /* We cannot do any checking for a SIZE that isn't known to be constant. Just build the index type and mark that it requires @@ -7532,10 +7536,16 @@ compute_array_index_type (tree name, tree size) { tree t = build_index_type (itype); TYPE_CANONICAL (abi_1_itype) = TYPE_CANONICAL (t); - return abi_1_itype; + itype = abi_1_itype; } else - return build_index_type (itype); + itype = build_index_type (itype); + + /* If the index type were dependent, we would have returned early, so + remember that it isn't. */ + TYPE_DEPENDENT_P (itype) = 0; + TYPE_DEPENDENT_P_VALID (itype) = 1; + return itype; } /* Returns the scope (if any) in which the entity declared by @@ -12664,7 +12674,7 @@ finish_function (int flags) if (!processing_template_decl && !cp_function_chain->can_throw && !flag_non_call_exceptions - && !DECL_REPLACEABLE_P (fndecl)) + && !decl_replaceable_p (fndecl)) TREE_NOTHROW (fndecl) = 1; /* This must come after expand_function_end because cleanups might diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 981b71f5452..be3dd2c9ad1 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1949,8 +1949,21 @@ dump_expr (tree t, int flags) case VIEW_CONVERT_EXPR: { tree op = TREE_OPERAND (t, 0); - - if (!same_type_p (TREE_TYPE (op), TREE_TYPE (t))) + tree ttype = TREE_TYPE (t); + tree optype = TREE_TYPE (op); + + if (TREE_CODE (ttype) != TREE_CODE (optype) + && POINTER_TYPE_P (ttype) + && POINTER_TYPE_P (optype) + && same_type_p (TREE_TYPE (optype), + TREE_TYPE (ttype))) + { + if (TREE_CODE (ttype) == REFERENCE_TYPE) + dump_unary_op ("*", t, flags); + else + dump_unary_op ("&", t, flags); + } + else if (!same_type_p (TREE_TYPE (op), TREE_TYPE (t))) { /* It is a cast, but we cannot tell whether it is a reinterpret or static cast. Use the C style notation. */ diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 03e28374810..39001c56a7d 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -2491,7 +2491,7 @@ write_expression (tree expr) tree scope = TREE_OPERAND (expr, 0); tree member = TREE_OPERAND (expr, 1); - if (!abi_version_at_least (2)) + if (!abi_version_at_least (2) && DECL_P (member)) { write_string ("sr"); write_type (scope); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 0ec38264062..1083e16dc55 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -259,9 +259,9 @@ make_alias_for_thunk (tree function) if (!flag_syntax_only) { - bool ok = cgraph_same_body_alias (alias, function); + struct cgraph_node *aliasn = cgraph_same_body_alias (alias, function); DECL_ASSEMBLER_NAME (function); - gcc_assert (ok); + gcc_assert (aliasn != NULL); } return alias; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5a90bdc6ead..f5e09ee1757 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17479,7 +17479,10 @@ dependent_type_p_r (tree type) } /* -- an array type constructed from any dependent type or whose size is specified by a constant expression that is - value-dependent. */ + value-dependent. + + We checked for type- and value-dependence of the bounds in + compute_array_index_type, so TYPE_DEPENDENT_P is already set. */ if (TREE_CODE (type) == ARRAY_TYPE) { if (TYPE_DOMAIN (type) @@ -17487,14 +17490,6 @@ dependent_type_p_r (tree type) return true; return dependent_type_p (TREE_TYPE (type)); } - else if (TREE_CODE (type) == INTEGER_TYPE - && !TREE_CONSTANT (TYPE_MAX_VALUE (type))) - { - /* If this is the TYPE_DOMAIN of an array type, consider it - dependent. We already checked for value-dependence in - compute_array_index_type. */ - return type_dependent_expression_p (TYPE_MAX_VALUE (type)); - } /* -- a template-id in which either the template name is a template parameter ... */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 0ac95d05b69..019c51eed85 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -3428,8 +3428,17 @@ warn_args_num (location_t loc, tree fndecl, bool too_many_p) "declared here"); } else - error_at (loc, too_many_p ? G_("too many arguments to function") - : G_("too few arguments to function")); + { + if (c_dialect_objc () && objc_message_selector ()) + error_at (loc, + too_many_p + ? G_("too many arguments to method %q#D") + : G_("too few arguments to method %q#D"), + objc_message_selector ()); + else + error_at (loc, too_many_p ? G_("too many arguments to function") + : G_("too few arguments to function")); + } } /* Convert the actual parameter expressions in the list VALUES to the diff --git a/gcc/df-core.c b/gcc/df-core.c index 181c1e7ce22..7c49ccddce9 100644 --- a/gcc/df-core.c +++ b/gcc/df-core.c @@ -1413,6 +1413,7 @@ df_get_bb_dirty (basic_block bb) void df_set_bb_dirty (basic_block bb) { + bb->flags |= BB_MODIFIED; if (df) { int p; diff --git a/gcc/df-problems.c b/gcc/df-problems.c index e18ffe3c5d9..82a0d0b6a57 100644 --- a/gcc/df-problems.c +++ b/gcc/df-problems.c @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "sbitmap.h" #include "bitmap.h" +#include "target.h" #include "timevar.h" #include "df.h" #include "except.h" @@ -3500,6 +3501,27 @@ df_simulate_find_defs (rtx insn, bitmap defs) } } +/* Find the set of uses for INSN. This includes partial defs. */ + +static void +df_simulate_find_uses (rtx insn, bitmap uses) +{ + df_ref *rec; + unsigned int uid = INSN_UID (insn); + + for (rec = DF_INSN_UID_DEFS (uid); *rec; rec++) + { + df_ref def = *rec; + if (DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)) + bitmap_set_bit (uses, DF_REF_REGNO (def)); + } + for (rec = DF_INSN_UID_USES (uid); *rec; rec++) + { + df_ref use = *rec; + bitmap_set_bit (uses, DF_REF_REGNO (use)); + } +} + /* Find the set of real DEFs, which are not clobbers, for INSN. */ void @@ -3727,7 +3749,301 @@ df_simulate_one_insn_forwards (basic_block bb, rtx insn, bitmap live) } df_simulate_fixup_sets (bb, live); } + +/* Used by the next two functions to encode information about the + memory references we found. */ +#define MEMREF_NORMAL 1 +#define MEMREF_VOLATILE 2 + +/* A subroutine of can_move_insns_across_p called through for_each_rtx. + Return either MEMREF_NORMAL or MEMREF_VOLATILE if a memory is found. */ + +static int +find_memory (rtx *px, void *data ATTRIBUTE_UNUSED) +{ + rtx x = *px; + + if (GET_CODE (x) == ASM_OPERANDS && MEM_VOLATILE_P (x)) + return MEMREF_VOLATILE; + + if (!MEM_P (x)) + return 0; + if (MEM_VOLATILE_P (x)) + return MEMREF_VOLATILE; + if (MEM_READONLY_P (x)) + return 0; + + return MEMREF_NORMAL; +} + +/* A subroutine of can_move_insns_across_p called through note_stores. + DATA points to an integer in which we set either the bit for + MEMREF_NORMAL or the bit for MEMREF_VOLATILE if we find a MEM + of either kind. */ + +static void +find_memory_stores (rtx x, const_rtx pat ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) +{ + int *pflags = (int *)data; + if (GET_CODE (x) == SUBREG) + x = XEXP (x, 0); + /* Treat stores to SP as stores to memory, this will prevent problems + when there are references to the stack frame. */ + if (x == stack_pointer_rtx) + *pflags |= MEMREF_VOLATILE; + if (!MEM_P (x)) + return; + *pflags |= MEM_VOLATILE_P (x) ? MEMREF_VOLATILE : MEMREF_NORMAL; +} + +/* Scan BB backwards, using df_simulate functions to keep track of + lifetimes, up to insn POINT. The result is stored in LIVE. */ + +void +simulate_backwards_to_point (basic_block bb, regset live, rtx point) +{ + rtx insn; + bitmap_copy (live, df_get_live_out (bb)); + df_simulate_initialize_backwards (bb, live); + + /* Scan and update life information until we reach the point we're + interested in. */ + for (insn = BB_END (bb); insn != point; insn = PREV_INSN (insn)) + df_simulate_one_insn_backwards (bb, insn, live); +} + +/* Return true if it is safe to move a group of insns, described by + the range FROM to TO, backwards across another group of insns, + described by ACROSS_FROM to ACROSS_TO. It is assumed that there + are no insns between ACROSS_TO and FROM, but they may be in + different basic blocks; MERGE_BB is the block from which the + insns will be moved. The caller must pass in a regset MERGE_LIVE + which specifies the registers live after TO. + + This function may be called in one of two cases: either we try to + move identical instructions from all successor blocks into their + predecessor, or we try to move from only one successor block. If + OTHER_BRANCH_LIVE is nonnull, it indicates that we're dealing with + the second case. It should contain a set of registers live at the + end of ACROSS_TO which must not be clobbered by moving the insns. + In that case, we're also more careful about moving memory references + and trapping insns. + + We return false if it is not safe to move the entire group, but it + may still be possible to move a subgroup. PMOVE_UPTO, if nonnull, + is set to point at the last moveable insn in such a case. */ +bool +can_move_insns_across (rtx from, rtx to, rtx across_from, rtx across_to, + basic_block merge_bb, regset merge_live, + regset other_branch_live, rtx *pmove_upto) +{ + rtx insn, next, max_to; + bitmap merge_set, merge_use, local_merge_live; + bitmap test_set, test_use; + unsigned i, fail = 0; + bitmap_iterator bi; + int memrefs_in_across = 0; + int mem_sets_in_across = 0; + bool trapping_insns_in_across = false; + + if (pmove_upto != NULL) + *pmove_upto = NULL_RTX; + + /* Find real bounds, ignoring debug insns. */ + while (!NONDEBUG_INSN_P (from) && from != to) + from = NEXT_INSN (from); + while (!NONDEBUG_INSN_P (to) && from != to) + to = PREV_INSN (to); + + for (insn = across_to; ; insn = next) + { + if (NONDEBUG_INSN_P (insn)) + { + memrefs_in_across |= for_each_rtx (&PATTERN (insn), find_memory, + NULL); + note_stores (PATTERN (insn), find_memory_stores, + &mem_sets_in_across); + /* This is used just to find sets of the stack pointer. */ + memrefs_in_across |= mem_sets_in_across; + trapping_insns_in_across |= may_trap_p (PATTERN (insn)); + } + next = PREV_INSN (insn); + if (insn == across_from) + break; + } + + /* Collect: + MERGE_SET = set of registers set in MERGE_BB + MERGE_USE = set of registers used in MERGE_BB and live at its top + MERGE_LIVE = set of registers live at the point inside the MERGE + range that we've reached during scanning + TEST_SET = set of registers set between ACROSS_FROM and ACROSS_END. + TEST_USE = set of registers used between ACROSS_FROM and ACROSS_END, + and live before ACROSS_FROM. */ + + merge_set = BITMAP_ALLOC (®_obstack); + merge_use = BITMAP_ALLOC (®_obstack); + local_merge_live = BITMAP_ALLOC (®_obstack); + test_set = BITMAP_ALLOC (®_obstack); + test_use = BITMAP_ALLOC (®_obstack); + + /* Compute the set of registers set and used in the ACROSS range. */ + if (other_branch_live != NULL) + bitmap_copy (test_use, other_branch_live); + df_simulate_initialize_backwards (merge_bb, test_use); + for (insn = across_to; ; insn = next) + { + if (NONDEBUG_INSN_P (insn)) + { + df_simulate_find_defs (insn, test_set); + df_simulate_defs (insn, test_use); + df_simulate_uses (insn, test_use); + } + next = PREV_INSN (insn); + if (insn == across_from) + break; + } + + /* Compute an upper bound for the amount of insns moved, by finding + the first insn in MERGE that sets a register in TEST_USE, or uses + a register in TEST_SET. We also check for calls, trapping operations, + and memory references. */ + max_to = NULL_RTX; + for (insn = from; ; insn = next) + { + if (CALL_P (insn)) + break; + if (NONDEBUG_INSN_P (insn)) + { + if (may_trap_p (PATTERN (insn)) + && (trapping_insns_in_across || other_branch_live != NULL)) + break; + + /* We cannot move memory stores past each other, or move memory + reads past stores, at least not without tracking them and + calling true_dependence on every pair. + + If there is no other branch and no memory references or + sets in the ACROSS range, we can move memory references + freely, even volatile ones. + + Otherwise, the rules are as follows: volatile memory + references and stores can't be moved at all, and any type + of memory reference can't be moved if there are volatile + accesses or stores in the ACROSS range. That leaves + normal reads, which can be moved, as the trapping case is + dealt with elsewhere. */ + if (other_branch_live != NULL || memrefs_in_across != 0) + { + int mem_ref_flags = 0; + int mem_set_flags = 0; + note_stores (PATTERN (insn), find_memory_stores, &mem_set_flags); + mem_ref_flags = for_each_rtx (&PATTERN (insn), find_memory, + NULL); + /* Catch sets of the stack pointer. */ + mem_ref_flags |= mem_set_flags; + + if ((mem_ref_flags | mem_set_flags) & MEMREF_VOLATILE) + break; + if ((memrefs_in_across & MEMREF_VOLATILE) && mem_ref_flags != 0) + break; + if (mem_set_flags != 0 + || (mem_sets_in_across != 0 && mem_ref_flags != 0)) + break; + } + df_simulate_find_uses (insn, merge_use); + /* We're only interested in uses which use a value live at + the top, not one previously set in this block. */ + bitmap_and_compl_into (merge_use, merge_set); + df_simulate_find_defs (insn, merge_set); + if (bitmap_intersect_p (merge_set, test_use) + || bitmap_intersect_p (merge_use, test_set)) + break; + max_to = insn; + } + next = NEXT_INSN (insn); + if (insn == to) + break; + } + if (max_to != to) + fail = 1; + + if (max_to == NULL_RTX || (fail && pmove_upto == NULL)) + goto out; + + /* Now, lower this upper bound by also taking into account that + a range of insns moved across ACROSS must not leave a register + live at the end that will be clobbered in ACROSS. We need to + find a point where TEST_SET & LIVE == 0. + + Insns in the MERGE range that set registers which are also set + in the ACROSS range may still be moved as long as we also move + later insns which use the results of the set, and make the + register dead again. This is verified by the condition stated + above. We only need to test it for registers that are set in + the moved region. + + MERGE_LIVE is provided by the caller and holds live registers after + TO. */ + bitmap_copy (local_merge_live, merge_live); + for (insn = to; insn != max_to; insn = PREV_INSN (insn)) + df_simulate_one_insn_backwards (merge_bb, insn, local_merge_live); + + /* We're not interested in registers that aren't set in the moved + region at all. */ + bitmap_and_into (local_merge_live, merge_set); + for (;;) + { + if (NONDEBUG_INSN_P (insn)) + { + if (!bitmap_intersect_p (test_set, local_merge_live)) + { + max_to = insn; + break; + } + + df_simulate_one_insn_backwards (merge_bb, insn, + local_merge_live); + } + if (insn == from) + { + fail = 1; + goto out; + } + insn = PREV_INSN (insn); + } + + if (max_to != to) + fail = 1; + + if (pmove_upto) + *pmove_upto = max_to; + + /* For small register class machines, don't lengthen lifetimes of + hard registers before reload. */ + if (! reload_completed + && targetm.small_register_classes_for_mode_p (VOIDmode)) + { + EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi) + { + if (i < FIRST_PSEUDO_REGISTER + && ! fixed_regs[i] + && ! global_regs[i]) + fail = 1; + } + } + + out: + BITMAP_FREE (merge_set); + BITMAP_FREE (merge_use); + BITMAP_FREE (local_merge_live); + BITMAP_FREE (test_set); + BITMAP_FREE (test_use); + + return !fail; +} /*---------------------------------------------------------------------------- @@ -971,7 +971,9 @@ extern void df_simulate_one_insn_backwards (basic_block, rtx, bitmap); extern void df_simulate_finalize_backwards (basic_block, bitmap); extern void df_simulate_initialize_forwards (basic_block, bitmap); extern void df_simulate_one_insn_forwards (basic_block, rtx, bitmap); - +extern void simulate_backwards_to_point (basic_block, regset, rtx); +extern bool can_move_insns_across (rtx, rtx, rtx, rtx, basic_block, regset, + regset, rtx *); /* Functions defined in df-scan.c. */ extern void df_scan_alloc (bitmap); diff --git a/gcc/doc/contrib.texi b/gcc/doc/contrib.texi index 7fe5aa4e96e..53f113dc100 100644 --- a/gcc/doc/contrib.texi +++ b/gcc/doc/contrib.texi @@ -80,7 +80,7 @@ Janne Blomqvist for contributions to GNU Fortran. Segher Boessenkool for various fixes. @item -Hans-J. Boehm for his @uref{http://www.hpl.hp.com/personal/Hans_Boehm/gc/,, +Hans-J. Boehm for his @uref{http://www.hpl.hp.com/@/personal/@/Hans_Boehm/@/gc/,, garbage collector}, IA-64 libffi port, and other Java work. @item diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi index 80a9df8911c..57624ed7497 100644 --- a/gcc/doc/cppopts.texi +++ b/gcc/doc/cppopts.texi @@ -188,8 +188,8 @@ without @samp{-pedantic} but treats as warnings. @item -M @opindex M -@cindex make -@cindex dependencies, make +@cindex @command{make} +@cindex dependencies, @command{make} Instead of outputting the result of preprocessing, output a rule suitable for @command{make} describing the dependencies of the main source file. The preprocessor outputs one @command{make} rule containing diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 4f2cc077101..7073c902abd 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -568,7 +568,7 @@ the containing function. You should specify, for @var{result}, a value returned by @code{__builtin_apply}. @end deftypefn -@deftypefn {Built-in Function} __builtin_va_arg_pack () +@deftypefn {Built-in Function} {} __builtin_va_arg_pack () This built-in function represents all anonymous arguments of an inline function. It can be used only in inline functions which will be always inlined, never compiled as a separate function, such as those using @@ -594,7 +594,7 @@ myprintf (FILE *f, const char *format, ...) @end smallexample @end deftypefn -@deftypefn {Built-in Function} __builtin_va_arg_pack_len () +@deftypefn {Built-in Function} {size_t} __builtin_va_arg_pack_len () This built-in function returns the number of anonymous arguments of an inline function. It can be used only in inline functions which will be always inlined, never compiled as a separate function, such @@ -796,8 +796,8 @@ This example is perfectly equivalent to x ? x : y @end smallexample -@cindex side effect in ?: -@cindex ?: side effect +@cindex side effect in @code{?:} +@cindex @code{?:} side effect @noindent In this simple case, the ability to omit the middle operand is not especially useful. When it becomes useful is when the first operand does, @@ -2671,6 +2671,31 @@ SRAM. The function will be put into a specific section named @code{.l1.text}. With @option{-mfdpic}, callers of such functions will use an inlined PLT. +@item leaf +@cindex @code{leaf} function attribute +Calls to external functions with this attribute must return to the current +compilation unit only by return or by exception handling. In particular, leaf +functions are not allowed to call callback function passed to it from current +compilation unit or directly call functions exported by the unit or longjmp +into the unit. Still leaf function might call functions from other complation +units and thus they are not neccesarily leaf in the sense that they contains no +function calls at all. + +The attribute is intended for library functions to improve dataflow analysis. +Compiler takes the hint that any data not escaping current compilation unit can +not be used or modified by the leaf function. For example, function @code{sin} +is leaf, function @code{qsort} is not. + +Note that the leaf functions might invoke signals and signal handlers might be +defined in the current compilation unit and use static variables. Only +compliant way to write such a signal handler is to declare such variables +@code{volatile}. + +The attribute has no effect on functions defined within current compilation +unit. This is to allow easy merging of multiple compilation units into one, +for example, by using the link time optimization. For this reason the +attribute is not allowed on types to annotate indirect calls. + @item long_call/short_call @cindex indirect calls on ARM This attribute specifies how a particular function is called on @@ -3900,7 +3925,7 @@ extension is irrelevant. @node C++ Comments @section C++ Style Comments -@cindex // +@cindex @code{//} @cindex C++ comments @cindex comments, C++ style @@ -12370,7 +12395,7 @@ bit-fields. See the Solaris man page for @code{cmn_err} for more information. @node Pragmas @section Pragmas Accepted by GCC @cindex pragmas -@cindex #pragma +@cindex @code{#pragma} GCC supports several types of pragmas, primarily in order to compile code originally written for other compilers. Note that in general @@ -12936,8 +12961,8 @@ versions earlier than 4.4. @node Unnamed Fields @section Unnamed struct/union fields within structs/unions -@cindex struct -@cindex union +@cindex @code{struct} +@cindex @code{union} As permitted by ISO C1X and for compatibility with other compilers, GCC allows you to define @@ -12989,7 +13014,7 @@ previously defined structure or union type with a tag. @section Thread-Local Storage @cindex Thread-Local Storage @cindex @acronym{TLS} -@cindex __thread +@cindex @code{__thread} Thread-local storage (@acronym{TLS}) is a mechanism by which variables are allocated such that there is one instance of the variable per extant @@ -13442,15 +13467,15 @@ vtable will still be emitted in every translation unit which defines it. Make sure that any inline virtuals are declared inline in the class body, even if they are not defined there. -@item type_info objects -@cindex type_info +@item @code{type_info} objects +@cindex @code{type_info} @cindex RTTI C++ requires information about types to be written out in order to implement @samp{dynamic_cast}, @samp{typeid} and exception handling. -For polymorphic classes (classes with virtual functions), the type_info +For polymorphic classes (classes with virtual functions), the @samp{type_info} object is written out along with the vtable so that @samp{dynamic_cast} can determine the dynamic type of a class object at runtime. For all -other types, we write out the type_info object when it is used: when +other types, we write out the @samp{type_info} object when it is used: when applying @samp{typeid} to an expression, throwing an object, or referring to a type in a catch clause or exception specification. @@ -13770,7 +13795,7 @@ Some attributes only make sense for C++ programs. @table @code @item init_priority (@var{priority}) -@cindex init_priority attribute +@cindex @code{init_priority} attribute In Standard C++, objects defined at namespace scope are guaranteed to be @@ -13795,7 +13820,7 @@ Note that the particular values of @var{priority} do not matter; only their relative ordering. @item java_interface -@cindex java_interface attribute +@cindex @code{java_interface} attribute This type attribute informs C++ that the class is a Java interface. It may only be applied to classes declared within an @code{extern "Java"} block. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 06a97ff0565..2db4e38738c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -161,10 +161,10 @@ in the following sections. @table @emph @item Overall Options @xref{Overall Options,,Options Controlling the Kind of Output}. -@gccoptlist{-c -S -E -o @var{file} -combine -no-canonical-prefixes @gol +@gccoptlist{-c -S -E -o @var{file} -no-canonical-prefixes @gol -pipe -pass-exit-codes @gol -x @var{language} -v -### --help@r{[}=@var{class}@r{[},@dots{}@r{]]} --target-help @gol ---version -wrapper@@@var{file} -fplugin=@var{file} -fplugin-arg-@var{name}=@var{arg} @gol +--version -wrapper @@@var{file} -fplugin=@var{file} -fplugin-arg-@var{name}=@var{arg} @gol -fdump-ada-spec@r{[}-slim@r{]}} @item C Language Options @@ -263,9 +263,9 @@ Objective-C and Objective-C++ Dialects}. -Wsystem-headers -Wtrampolines -Wtrigraphs -Wtype-limits -Wundef @gol -Wuninitialized -Wunknown-pragmas -Wno-pragmas @gol -Wunsuffixed-float-constants -Wunused -Wunused-function @gol --Wunused-label -Wunused-parameter -Wno-unused-result -Wunused-value -Wunused-variable @gol --Wunused-but-set-parameter -Wunused-but-set-variable -Wvariadic-macros -Wvla @gol --Wvolatile-register-var -Wwrite-strings} +-Wunused-label -Wunused-parameter -Wno-unused-result -Wunused-value @gol +-Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable @gol +-Wvariadic-macros -Wvla -Wvolatile-register-var -Wwrite-strings} @item C and Objective-C-only Warning Options @gccoptlist{-Wbad-function-cast -Wmissing-declarations @gol @@ -330,13 +330,13 @@ Objective-C and Objective-C++ Dialects}. @item Optimization Options @xref{Optimize Options,,Options that Control Optimization}. -@gccoptlist{ --falign-functions[=@var{n}] -falign-jumps[=@var{n}] @gol +@gccoptlist{-falign-functions[=@var{n}] -falign-jumps[=@var{n}] @gol -falign-labels[=@var{n}] -falign-loops[=@var{n}] -fassociative-math @gol -fauto-inc-dec -fbranch-probabilities -fbranch-target-load-optimize @gol -fbranch-target-load-optimize2 -fbtr-bb-exclusive -fcaller-saves @gol -fcheck-data-deps -fconserve-stack -fcprop-registers -fcrossjumping @gol --fcse-follow-jumps -fcse-skip-blocks -fcx-fortran-rules -fcx-limited-range @gol +-fcse-follow-jumps -fcse-skip-blocks -fcx-fortran-rules @gol +-fcx-limited-range @gol -fdata-sections -fdce -fdce @gol -fdelayed-branch -fdelete-null-pointer-checks -fdse -fdse @gol -fearly-inlining -fipa-sra -fexpensive-optimizations -ffast-math @gol @@ -345,24 +345,26 @@ Objective-C and Objective-C++ Dialects}. -fgcse -fgcse-after-reload -fgcse-las -fgcse-lm -fgraphite-identity @gol -fgcse-sm -fif-conversion -fif-conversion2 -findirect-inlining @gol -finline-functions -finline-functions-called-once -finline-limit=@var{n} @gol --finline-small-functions -fipa-cp -fipa-cp-clone -fipa-matrix-reorg -fipa-pta @gol --fipa-profile -fipa-pure-const -fipa-reference -fipa-struct-reorg @gol --fira-algorithm=@var{algorithm} @gol +-finline-small-functions -fipa-cp -fipa-cp-clone -fipa-matrix-reorg @gol +-fipa-pta -fipa-profile -fipa-pure-const -fipa-reference @gol +-fipa-struct-reorg -fira-algorithm=@var{algorithm} @gol -fira-region=@var{region} -fira-coalesce @gol -fira-loop-pressure -fno-ira-share-save-slots @gol -fno-ira-share-spill-slots -fira-verbose=@var{n} @gol -fivopts -fkeep-inline-functions -fkeep-static-consts @gol -floop-block -floop-interchange -floop-strip-mine @gol --floop-parallelize-all -flto -flto-compression-level -flto-report -fltrans @gol --fltrans-output-list -fmerge-all-constants -fmerge-constants -fmodulo-sched @gol --fmodulo-sched-allow-regmoves -fmove-loop-invariants -fmudflap @gol --fmudflapir -fmudflapth -fno-branch-count-reg -fno-default-inline @gol +-floop-parallelize-all -flto -flto-compression-level -flto-report @gol +-fltrans -fltrans-output-list -fmerge-all-constants -fmerge-constants @gol +-fmodulo-sched -fmodulo-sched-allow-regmoves -fmove-loop-invariants @gol +-fmudflap -fmudflapir -fmudflapth -fno-branch-count-reg @gol +-fno-default-inline @gol -fno-defer-pop -fno-function-cse -fno-guess-branch-probability @gol -fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol -fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol -fomit-frame-pointer -foptimize-register-move -foptimize-sibling-calls @gol --fpartial-inlining -fpeel-loops -fpredictive-commoning -fprefetch-loop-arrays @gol +-fpartial-inlining -fpeel-loops -fpredictive-commoning @gol +-fprefetch-loop-arrays @gol -fprofile-correction -fprofile-dir=@var{path} -fprofile-generate @gol -fprofile-generate=@var{path} @gol -fprofile-use -fprofile-use=@var{path} -fprofile-values @gol @@ -380,7 +382,8 @@ Objective-C and Objective-C++ Dialects}. -fsel-sched-pipelining -fsel-sched-pipelining-outer-loops @gol -fsignaling-nans -fsingle-precision-constant -fsplit-ivs-in-unroller @gol -fsplit-wide-types -fstack-protector -fstack-protector-all @gol --fstrict-aliasing -fstrict-overflow -fthread-jumps -ftracer -ftree-bit-ccp @gol +-fstrict-aliasing -fstrict-overflow -fthread-jumps -ftracer @gol +-ftree-bit-ccp @gol -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-copy-prop @gol -ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse @gol -ftree-forwprop -ftree-fre -ftree-loop-if-convert @gol @@ -590,7 +593,7 @@ Objective-C and Objective-C++ Dialects}. -mno-fp-ret-in-387 -msoft-float @gol -mno-wide-multiply -mrtd -malign-double @gol -mpreferred-stack-boundary=@var{num} --mincoming-stack-boundary=@var{num} +-mincoming-stack-boundary=@var{num} @gol -mcld -mcx16 -msahf -mmovbe -mcrc32 -mrecip @gol -mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx @gol -maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfused-madd @gol @@ -737,7 +740,7 @@ Objective-C and Objective-C++ Dialects}. -msplit -mno-split -munix-asm -mdec-asm} @emph{picoChip Options} -@gccoptlist{-mae=@var{ae_type} -mvliw-lookahead=@var{N} +@gccoptlist{-mae=@var{ae_type} -mvliw-lookahead=@var{N} @gol -msymbol-as-address -mno-inefficient-warnings} @emph{PowerPC Options} @@ -890,8 +893,8 @@ See i386 and x86-64 Options. @emph{i386 and x86-64 Windows Options} @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll --mnop-fun-dllimport -mthread -municode -mwin32 -mwindows --fno-set-stack-executable} +-mnop-fun-dllimport -mthread @gol +-municode -mwin32 -mwindows -fno-set-stack-executable} @emph{Xstormy16 Options} @gccoptlist{-msim} @@ -1196,23 +1199,6 @@ various stages of compilation. This fails to work on some systems where the assembler is unable to read from a pipe; but the GNU assembler has no trouble. -@item -combine -@opindex combine -If you are compiling multiple source files, this option tells the driver -to pass all the source files to the compiler at once (for those -languages for which the compiler can handle this). This will allow -intermodule analysis (IMA) to be performed by the compiler. Currently the only -language for which this is supported is C@. If you pass source files for -multiple languages to the driver, using this option, the driver will invoke -the compiler(s) that support IMA once each, passing each compiler all the -source files appropriate for it. For those languages that do not support -IMA this option will be ignored, and the compiler will be invoked once for -each source file in that language. If you use this option in conjunction -with @option{-save-temps}, the compiler will generate multiple -pre-processed files -(one for each source file), but only one (combined) @file{.o} or -@file{.s} file. - @item --help @opindex help Print (on the standard output) a description of the command line options @@ -1677,7 +1663,7 @@ freestanding and hosted environments. @item -fopenmp @opindex fopenmp -@cindex openmp parallel +@cindex OpenMP parallel Enable handling of OpenMP directives @code{#pragma omp} in C/C++ and @code{!$omp} in Fortran. When @option{-fopenmp} is specified, the compiler generates parallel code according to the OpenMP Application @@ -2422,8 +2408,8 @@ less vulnerable to unintended effects and much easier to search for. @item -Woverloaded-virtual @r{(C++ and Objective-C++ only)} @opindex Woverloaded-virtual @opindex Wno-overloaded-virtual -@cindex overloaded virtual fn, warning -@cindex warning for overloaded virtual fn +@cindex overloaded virtual function, warning +@cindex warning for overloaded virtual function Warn when a function declaration hides virtual functions from a base class. For example, in: @@ -2535,11 +2521,11 @@ used. @item -fno-nil-receivers @opindex fno-nil-receivers -Assume that all Objective-C message dispatches (e.g., -@code{[receiver message:arg]}) in this translation unit ensure that the receiver -is not @code{nil}. This allows for more efficient entry points in the runtime -to be used. Currently, this option is only available in conjunction with -the NeXT runtime on Mac OS X 10.3 and later. +Assume that all Objective-C message dispatches (@code{[receiver +message:arg]}) in this translation unit ensure that the receiver is +not @code{nil}. This allows for more efficient entry points in the +runtime to be used. Currently, this option is only available in +conjunction with the NeXT runtime on Mac OS X 10.3 and later. @item -fobjc-call-cxx-cdtors @opindex fobjc-call-cxx-cdtors @@ -2552,14 +2538,15 @@ is a C++ object with a non-trivial destructor, and if so, synthesize a special @code{- (void) .cxx_destruct} method that will run all such default destructors, in reverse order. -The @code{- (id) .cxx_construct} and/or @code{- (void) .cxx_destruct} methods -thusly generated will only operate on instance variables declared in the -current Objective-C class, and not those inherited from superclasses. It -is the responsibility of the Objective-C runtime to invoke all such methods -in an object's inheritance hierarchy. The @code{- (id) .cxx_construct} methods -will be invoked by the runtime immediately after a new object -instance is allocated; the @code{- (void) .cxx_destruct} methods will -be invoked immediately before the runtime deallocates an object instance. +The @code{- (id) .cxx_construct} and @code{- (void) .cxx_destruct} +methods thusly generated will only operate on instance variables +declared in the current Objective-C class, and not those inherited +from superclasses. It is the responsibility of the Objective-C +runtime to invoke all such methods in an object's inheritance +hierarchy. The @code{- (id) .cxx_construct} methods will be invoked +by the runtime immediately after a new object instance is allocated; +the @code{- (void) .cxx_destruct} methods will be invoked immediately +before the runtime deallocates an object instance. As of this writing, only the NeXT runtime on Mac OS X 10.4 and later has support for invoking the @code{- (id) .cxx_construct} and @@ -2572,100 +2559,20 @@ accomplished via the comm page. @item -fobjc-exceptions @opindex fobjc-exceptions -Enable syntactic support for structured exception handling in Objective-C, -similar to what is offered by C++ and Java. This option is -unavailable in conjunction with the NeXT runtime on Mac OS X 10.2 and -earlier. - -@smallexample - @@try @{ - @dots{} - @@throw expr; - @dots{} - @} - @@catch (AnObjCClass *exc) @{ - @dots{} - @@throw expr; - @dots{} - @@throw; - @dots{} - @} - @@catch (AnotherClass *exc) @{ - @dots{} - @} - @@catch (id allOthers) @{ - @dots{} - @} - @@finally @{ - @dots{} - @@throw expr; - @dots{} - @} -@end smallexample - -The @code{@@throw} statement may appear anywhere in an Objective-C or -Objective-C++ program; when used inside of a @code{@@catch} block, the -@code{@@throw} may appear without an argument (as shown above), in which case -the object caught by the @code{@@catch} will be rethrown. - -Note that only (pointers to) Objective-C objects may be thrown and -caught using this scheme. When an object is thrown, it will be caught -by the nearest @code{@@catch} clause capable of handling objects of that type, -analogously to how @code{catch} blocks work in C++ and Java. A -@code{@@catch(id @dots{})} clause (as shown above) may also be provided to catch -any and all Objective-C exceptions not caught by previous @code{@@catch} -clauses (if any). - -The @code{@@finally} clause, if present, will be executed upon exit from the -immediately preceding @code{@@try @dots{} @@catch} section. This will happen -regardless of whether any exceptions are thrown, caught or rethrown -inside the @code{@@try @dots{} @@catch} section, analogously to the behavior -of the @code{finally} clause in Java. - -There are several caveats to using the new exception mechanism: - -@itemize @bullet -@item -Although currently designed to be binary compatible with @code{NS_HANDLER}-style -idioms provided by the @code{NSException} class, the new -exceptions can only be used on Mac OS X 10.3 (Panther) and later -systems, due to additional functionality needed in the (NeXT) Objective-C -runtime. - -@item -As mentioned above, the new exceptions do not support handling -types other than Objective-C objects. Furthermore, when used from -Objective-C++, the Objective-C exception model does not interoperate with C++ -exceptions at this time. This means you cannot @code{@@throw} an exception -from Objective-C and @code{catch} it in C++, or vice versa -(i.e., @code{throw @dots{} @@catch}). -@end itemize - -The @option{-fobjc-exceptions} switch also enables the use of synchronization -blocks for thread-safe execution: - -@smallexample - @@synchronized (ObjCClass *guard) @{ - @dots{} - @} -@end smallexample - -Upon entering the @code{@@synchronized} block, a thread of execution shall -first check whether a lock has been placed on the corresponding @code{guard} -object by another thread. If it has, the current thread shall wait until -the other thread relinquishes its lock. Once @code{guard} becomes available, -the current thread will place its own lock on it, execute the code contained in -the @code{@@synchronized} block, and finally relinquish the lock (thereby -making @code{guard} available to other threads). - -Unlike Java, Objective-C does not allow for entire methods to be marked -@code{@@synchronized}. Note that throwing exceptions out of -@code{@@synchronized} blocks is allowed, and will cause the guarding object -to be unlocked properly. +Enable syntactic support for structured exception handling in +Objective-C, similar to what is offered by C++ and Java. This option +is required to use the Objective-C keywords @code{@@try}, +@code{@@throw}, @code{@@catch}, @code{@@finally} and +@code{@@synchronized}. This option is available with both the GNU +runtime and the NeXT runtime (but not available in conjunction with +the NeXT runtime on Mac OS X 10.2 and earlier). @item -fobjc-gc @opindex fobjc-gc -Enable garbage collection (GC) in Objective-C and Objective-C++ programs. +Enable garbage collection (GC) in Objective-C and Objective-C++ +programs. This option is only available with the NeXT runtime; the +GNU runtime has a different garbage collection implementation that +does not require special compiler flags. @item -freplace-objc-classes @opindex freplace-objc-classes @@ -2687,6 +2594,8 @@ which improves run-time performance. Specifying the @option{-fzero-link} flag suppresses this behavior and causes calls to @code{objc_getClass("@dots{}")} to be retained. This is useful in Zero-Link debugging mode, since it allows for individual class implementations to be modified during program execution. +The GNU runtime currently always retains calls to @code{objc_get_class("@dots{}")} +regardless of command line options. @item -gen-decls @opindex gen-decls @@ -3370,7 +3279,7 @@ The standard is worded confusingly, therefore there is some debate over the precise meaning of the sequence point rules in subtle cases. Links to discussions of the problem, including proposed formal definitions, may be found on the GCC readings page, at -@w{@uref{http://gcc.gnu.org/readings.html}}. +@uref{http://gcc.gnu.org/@/readings.html}. This warning is enabled by @option{-Wall} for C and C++. @@ -4781,7 +4690,7 @@ This option is a detailed version of @option{-femit-struct-debug-reduced} and @option{-femit-struct-debug-baseonly}, which will serve for most needs. -A specification has the syntax +A specification has the syntax@* [@samp{dir:}|@samp{ind:}][@samp{ord:}|@samp{gen:}](@samp{any}|@samp{sys}|@samp{base}|@samp{none}) The optional first word limits the specification to @@ -6762,7 +6671,7 @@ layout in order to better utilize spatial locality. This transformation is affective for programs containing arrays of structures. Available in two compilation modes: profile-based (enabled with @option{-fprofile-generate}) or static (which uses built-in heuristics). It works only in whole program -mode, so it requires @option{-fwhole-program} and @option{-combine} to be +mode, so it requires @option{-fwhole-program} to be enabled. Structures considered @samp{cold} by this transformation are not affected (see @option{--param struct-reorg-cold-struct-ratio=@var{value}}). @@ -7467,7 +7376,7 @@ and those merged by attribute @code{externally_visible} become static functions and in effect are optimized more aggressively by interprocedural optimizers. If @command{gold} is used as the linker plugin, @code{externally_visible} attributes are automatically added to functions (not variable yet due to a current @command{gold} issue) that are accessed outside of LTO objects according to resolution file produced by @command{gold}. For other linkers that cannot generate resolution file, explicit @code{externally_visible} attributes are still necessary. While this option is equivalent to proper use of the @code{static} keyword for programs consisting of a single file, in combination with option -@option{-combine}, @option{-flto} or @option{-fwhopr} this flag can be used to +@option{-flto} or @option{-fwhopr} this flag can be used to compile many smaller scale programs since the functions and variables become local for the whole combined compilation unit, not for the single source file itself. @@ -9338,17 +9247,17 @@ appear here are: @table @code @item %include <@var{file}> -@cindex %include +@cindex @code{%include} Search for @var{file} and insert its text at the current point in the specs file. @item %include_noerr <@var{file}> -@cindex %include_noerr +@cindex @code{%include_noerr} Just like @samp{%include}, but do not generate an error message if the include file cannot be found. @item %rename @var{old_name} @var{new_name} -@cindex %rename +@cindex @code{%rename} Rename the spec string @var{old_name} to @var{new_name}. @end table @@ -10914,6 +10823,7 @@ one controlled by the @option{-mcpu} or @option{-march} option. @itemx -dynamic @itemx -exported_symbols_list @itemx -filelist +@need 800 @itemx -flat_namespace @itemx -force_flat_namespace @itemx -headerpad_max_install_names @@ -10924,6 +10834,7 @@ one controlled by the @option{-mcpu} or @option{-march} option. @itemx -multi_module @itemx -multiply_defined @itemx -multiply_defined_unused +@need 800 @itemx -noall_load @itemx -no_dead_strip_inits_and_terms @itemx -nofixprebinding @@ -10934,6 +10845,7 @@ one controlled by the @option{-mcpu} or @option{-march} option. @itemx -prebind @itemx -prebind_all_twolevel_modules @itemx -private_bundle +@need 800 @itemx -read_only_relocs @itemx -sectalign @itemx -sectobjectsymbols @@ -10944,6 +10856,7 @@ one controlled by the @option{-mcpu} or @option{-march} option. @itemx -sectorder @itemx -segaddr @itemx -segs_read_only_addr +@need 800 @itemx -segs_read_write_addr @itemx -seg_addr_table @itemx -seg_addr_table_filename @@ -10954,6 +10867,7 @@ one controlled by the @option{-mcpu} or @option{-march} option. @itemx -single_module @itemx -static @itemx -sub_library +@need 800 @itemx -sub_umbrella @itemx -twolevel_namespace @itemx -umbrella @@ -12034,7 +11948,7 @@ for the ABI and the set of available instructions. The choices for @var{cpu-type} are: @table @emph @item generic -Produce code optimized for the most common IA32/AMD64/EM64T processors. +Produce code optimized for the most common IA32/@/AMD64/@/EM64T processors. If you know the CPU on which your code will run, then you should use the corresponding @option{-mtune} option instead of @option{-mtune=generic}. But, if you do not know exactly what CPU users @@ -12412,6 +12326,7 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. @itemx -mssse3 @itemx -mno-ssse3 @itemx -msse4.1 +@need 800 @itemx -mno-sse4.1 @itemx -msse4.2 @itemx -mno-sse4.2 @@ -12422,6 +12337,7 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. @itemx -maes @itemx -mno-aes @itemx -mpclmul +@need 800 @itemx -mno-pclmul @itemx -mfsgsbase @itemx -mno-fsgsbase @@ -12432,6 +12348,7 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. @itemx -msse4a @itemx -mno-sse4a @itemx -mfma4 +@need 800 @itemx -mno-fma4 @itemx -mxop @itemx -mno-xop @@ -14064,7 +13981,7 @@ generates 64-bit code when you select a 64-bit architecture, but you can use @option{-mgp32} to get 32-bit code instead. For information about the O64 ABI, see -@w{@uref{http://gcc.gnu.org/projects/mipso64-abi.html}}. +@uref{http://gcc.gnu.org/@/projects/@/mipso64-abi.html}. GCC supports a variant of the o32 ABI in which floating-point registers are 64 rather than 32 bits wide. You can select this combination with @@ -15032,6 +14949,7 @@ These @samp{-m} options are defined for the IBM RS/6000 and PowerPC: @itemx -mno-powerpc-gpopt @itemx -mpowerpc-gfxopt @itemx -mno-powerpc-gfxopt +@need 800 @itemx -mpowerpc64 @itemx -mno-powerpc64 @itemx -mmfcrf @@ -15042,6 +14960,7 @@ These @samp{-m} options are defined for the IBM RS/6000 and PowerPC: @itemx -mno-popcntd @itemx -mfprnd @itemx -mno-fprnd +@need 800 @itemx -mcmpb @itemx -mno-cmpb @itemx -mmfpgpr @@ -17859,8 +17778,13 @@ that function is not instrumented. The match is done on substrings: if the @var{file} parameter is a substring of the file name, it is considered to be a match. -For example, -@code{-finstrument-functions-exclude-file-list=/bits/stl,include/sys} +For example: + +@smallexample +-finstrument-functions-exclude-file-list=/bits/stl,include/sys +@end smallexample + +@noindent will exclude any inline function defined in files whose pathnames contain @code{/bits/stl} or @code{include/sys}. @@ -18024,7 +17948,7 @@ visibility so that the @samp{type_info} nodes will be unified between the DSOs. An overview of these techniques, their benefits and how to use them -is at @w{@uref{http://gcc.gnu.org/wiki/Visibility}}. +is at @uref{http://gcc.gnu.org/@/wiki/@/Visibility}. @item -fstrict-volatile-bitfields This option should be used if accesses to volatile bitfields (or other diff --git a/gcc/doc/objc.texi b/gcc/doc/objc.texi index c15c1acf848..1beb748cfc2 100644 --- a/gcc/doc/objc.texi +++ b/gcc/doc/objc.texi @@ -6,13 +6,11 @@ @node Objective-C @comment node-name, next, previous, up -@chapter GNU Objective-C runtime features +@chapter GNU Objective-C features -This document is meant to describe some of the GNU Objective-C runtime -features. It is not intended to teach you Objective-C, there are several -resources on the Internet that present the language. Questions and -comments about this document to Ovidiu Predescu -@email{ovidiu@@cup.hp.com}. +This document is meant to describe some of the GNU Objective-C +features. It is not intended to teach you Objective-C, there are +several resources on the Internet that present the language. @menu * Executing code before main:: @@ -20,9 +18,11 @@ comments about this document to Ovidiu Predescu * Garbage Collection:: * Constant string objects:: * compatibility_alias:: +* Exceptions:: +* Synchronization:: @end menu -@node Executing code before main, Type encoding, Objective-C, Objective-C +@node Executing code before main @section @code{+load}: Executing code before main The GNU Objective-C runtime provides a way that allows you to execute @@ -103,7 +103,7 @@ instead of @code{+initialize}. @end menu -@node What you can and what you cannot do in +load, , Executing code before main, Executing code before main +@node What you can and what you cannot do in +load @subsection What you can and what you cannot do in @code{+load} The @code{+load} implementation in the GNU runtime guarantees you the following @@ -167,7 +167,7 @@ above apply to classes defined in bundle. -@node Type encoding, Garbage Collection, Executing code before main, Objective-C +@node Type encoding @section Type encoding The Objective-C compiler generates type encodings for all the @@ -311,21 +311,19 @@ however, the type specifiers are only encoded when they appear in method argument types. -@node Garbage Collection, Constant string objects, Type encoding, Objective-C +@node Garbage Collection @section Garbage Collection -Support for a new memory management policy has been added by using a -powerful conservative garbage collector, known as the -Boehm-Demers-Weiser conservative garbage collector. It is available from -@w{@uref{http://www.hpl.hp.com/personal/Hans_Boehm/gc/}}. +Support for garbage collection with the GNU runtime has been added by +using a powerful conservative garbage collector, known as the +Boehm-Demers-Weiser conservative garbage collector. -To enable the support for it you have to configure the compiler using an -additional argument, @w{@option{--enable-objc-gc}}. You need to have -garbage collector installed before building the compiler. This will -build an additional runtime library which has several enhancements to -support the garbage collector. The new library has a new name, -@file{libobjc_gc.a} to not conflict with the non-garbage-collected -library. +To enable the support for it you have to configure the compiler using +an additional argument, @w{@option{--enable-objc-gc}}. This will +build the boehm-gc library, and build an additional runtime library +which has several enhancements to support the garbage collector. The +new library has a new name, @file{libobjc_gc.a} to not conflict with +the non-garbage-collected library. When the garbage collector is used, the objects are allocated using the so-called typed memory allocation mechanism available in the @@ -452,10 +450,6 @@ restrictions in doing this. @node compatibility_alias @section compatibility_alias -This is a feature of the Objective-C compiler rather than of the -runtime, anyway since it is documented nowhere and its existence was -forgotten, we are documenting it here. - The keyword @code{@@compatibility_alias} allows you to define a class name as equivalent to another class name. For example: @@ -476,3 +470,114 @@ There are some constraints on how this can be used--- @item @code{GSWApplication} (the real class) must be an existing class. @end itemize + +@c ========================================================================= +@node Exceptions +@section Exceptions + +GNU Objective-C provides exception support built into the language, as +in the following example: + +@smallexample + @@try @{ + @dots{} + @@throw expr; + @dots{} + @} + @@catch (AnObjCClass *exc) @{ + @dots{} + @@throw expr; + @dots{} + @@throw; + @dots{} + @} + @@catch (AnotherClass *exc) @{ + @dots{} + @} + @@catch (id allOthers) @{ + @dots{} + @} + @@finally @{ + @dots{} + @@throw expr; + @dots{} + @} +@end smallexample + +The @code{@@throw} statement may appear anywhere in an Objective-C or +Objective-C++ program; when used inside of a @code{@@catch} block, the +@code{@@throw} may appear without an argument (as shown above), in +which case the object caught by the @code{@@catch} will be rethrown. + +Note that only (pointers to) Objective-C objects may be thrown and +caught using this scheme. When an object is thrown, it will be caught +by the nearest @code{@@catch} clause capable of handling objects of +that type, analogously to how @code{catch} blocks work in C++ and +Java. A @code{@@catch(id @dots{})} clause (as shown above) may also +be provided to catch any and all Objective-C exceptions not caught by +previous @code{@@catch} clauses (if any). + +The @code{@@finally} clause, if present, will be executed upon exit +from the immediately preceding @code{@@try @dots{} @@catch} section. +This will happen regardless of whether any exceptions are thrown, +caught or rethrown inside the @code{@@try @dots{} @@catch} section, +analogously to the behavior of the @code{finally} clause in Java. + +There are several caveats to using the new exception mechanism: + +@itemize @bullet +@item +The @option{-fobjc-exceptions} command line option must be used when +compiling Objective-C files that use exceptions. + +@item +With the GNU runtime, exceptions are always implemented as ``native'' +exceptions and it is recommended that the @option{-fexceptions} and +@option{-shared-libgcc} options are used when linking. + +@item +With the NeXT runtime, although currently designed to be binary +compatible with @code{NS_HANDLER}-style idioms provided by the +@code{NSException} class, the new exceptions can only be used on Mac +OS X 10.3 (Panther) and later systems, due to additional functionality +needed in the NeXT Objective-C runtime. + +@item +As mentioned above, the new exceptions do not support handling +types other than Objective-C objects. Furthermore, when used from +Objective-C++, the Objective-C exception model does not interoperate with C++ +exceptions at this time. This means you cannot @code{@@throw} an exception +from Objective-C and @code{catch} it in C++, or vice versa +(i.e., @code{throw @dots{} @@catch}). +@end itemize + +@c ========================================================================= +@node Synchronization +@section Synchronization + +GNU Objective-C provides support for synchronized blocks: + +@smallexample + @@synchronized (ObjCClass *guard) @{ + @dots{} + @} +@end smallexample + +Upon entering the @code{@@synchronized} block, a thread of execution +shall first check whether a lock has been placed on the corresponding +@code{guard} object by another thread. If it has, the current thread +shall wait until the other thread relinquishes its lock. Once +@code{guard} becomes available, the current thread will place its own +lock on it, execute the code contained in the @code{@@synchronized} +block, and finally relinquish the lock (thereby making @code{guard} +available to other threads). + +Unlike Java, Objective-C does not allow for entire methods to be +marked @code{@@synchronized}. Note that throwing exceptions out of +@code{@@synchronized} blocks is allowed, and will cause the guarding +object to be unlocked properly. + +Because of the interactions between synchronization and exception +handling, you can only use @code{@@synchronized} when compiling with +exceptions enabled, that is with the command line option +@option{-fobjc-exceptions}. diff --git a/gcc/doc/options.texi b/gcc/doc/options.texi index c224bbdd039..924ac179304 100644 --- a/gcc/doc/options.texi +++ b/gcc/doc/options.texi @@ -41,6 +41,17 @@ records have two fields: the string @samp{TargetSave}, and a declaration type to go in the @code{cl_target_option} structure. @item +A variable record to define a variable used to store option +information. These records have two fields: the string +@samp{Variable}, and a declaration of the type and name of the +variable, optionally with an initializer (but without any trailing +@samp{;}). These records may be used for variables used for many +options where declaring the variable and its initializer by omitting +@code{VarExists} from a single option definition record would be +inappropriate, or for variables set in option handlers rather than +referenced by @code{Var} properties. + +@item An option definition record. These records have the following fields: @enumerate @item diff --git a/gcc/doc/standards.texi b/gcc/doc/standards.texi index 38072df0356..67753db9cbe 100644 --- a/gcc/doc/standards.texi +++ b/gcc/doc/standards.texi @@ -188,9 +188,9 @@ changes to the C++ language, some of which have been implemented in an experimental C++0x mode in GCC@. The C++0x mode in GCC tracks the draft working paper for the C++0x standard; the latest working paper is available on the ISO C++ committee's web site at -@uref{http://www.open-std.org/jtc1/sc22/wg21/}. For information +@uref{http://www.open-std.org/@/jtc1/@/sc22/@/wg21/}. For information regarding the C++0x features available in the experimental C++0x mode, -see @uref{http://gcc.gnu.org/projects/cxx0x.html}. To select this +see @uref{http://gcc.gnu.org/projects/@/cxx0x.html}. To select this standard in GCC, use the option @option{-std=c++0x}; to obtain all the diagnostics required by the standard, you should also specify @option{-pedantic} (or @option{-pedantic-errors} if you want them to be @@ -214,7 +214,7 @@ Objective-C Language'', available at a number of web sites: @itemize @item -@uref{http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/} +@uref{http://developer.apple.com/@/mac/@/library/@/documentation/@/Cocoa/@/Conceptual/@/ObjectiveC/} is a recent (and periodically updated) version; @item @uref{http://objc.toodarkpark.net} diff --git a/gcc/doc/trouble.texi b/gcc/doc/trouble.texi index 703f2ed5567..03e399373b4 100644 --- a/gcc/doc/trouble.texi +++ b/gcc/doc/trouble.texi @@ -385,7 +385,7 @@ such as @samp{+=}. GCC, following the ISO standard, does not allow this. @cindex apostrophes -@cindex ' +@cindex @code{'} @item GCC complains about unterminated character constants inside of preprocessing conditionals that fail. Some programs have English diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 5ee14ee6bcf..900994d0bed 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -800,6 +800,9 @@ dwarf2out_cfi_label (bool force) /* True if remember_state should be emitted before following CFI directive. */ static bool emit_cfa_remember; +/* True if any CFI directives were emitted at the current insn. */ +static bool any_cfis_emitted; + /* Add CFI to the current fde at the PC value indicated by LABEL if specified, or to the CIE if LABEL is NULL. */ @@ -879,6 +882,7 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi) output_cfi_directive (cfi); list_head = &fde->dw_fde_cfi; + any_cfis_emitted = true; } /* ??? If this is a CFI for the CIE, we don't emit. This assumes that the standard CIE contents that the assembler @@ -916,6 +920,7 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi) } list_head = &fde->dw_fde_cfi; + any_cfis_emitted = true; } add_cfi (list_head, cfi); @@ -2745,6 +2750,7 @@ dwarf2out_frame_debug (rtx insn, bool after_p) } label = dwarf2out_cfi_label (false); + any_cfis_emitted = false; for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) switch (REG_NOTE_KIND (note)) @@ -2830,7 +2836,11 @@ dwarf2out_frame_debug (rtx insn, bool after_p) break; } if (handled_one) - return; + { + if (any_cfis_emitted) + dwarf2out_flush_queued_reg_saves (); + return; + } insn = PATTERN (insn); found: @@ -2839,7 +2849,7 @@ dwarf2out_frame_debug (rtx insn, bool after_p) /* Check again. A parallel can save and update the same register. We could probably check just once, here, but this is safer than removing the check above. */ - if (clobbers_queued_reg_save (insn)) + if (any_cfis_emitted || clobbers_queued_reg_save (insn)) dwarf2out_flush_queued_reg_saves (); } @@ -5868,7 +5878,7 @@ skeleton_chain_node; static unsigned long next_die_offset; /* Record the root of the DIE's built for the current compilation unit. */ -static GTY(()) dw_die_ref comp_unit_die; +static GTY(()) dw_die_ref single_comp_unit_die; /* A list of type DIEs that have been separated into comdat sections. */ static GTY(()) comdat_type_node *comdat_type_list; @@ -6488,6 +6498,15 @@ static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES]; #endif +/* Return the root of the DIE's built for the current compilation unit. */ +static dw_die_ref +comp_unit_die (void) +{ + if (!single_comp_unit_die) + single_comp_unit_die = gen_compile_unit_die (NULL); + return single_comp_unit_die; +} + /* We allow a language front-end to designate a function that is to be called to "demangle" any name before it is put into a DIE. */ @@ -7681,7 +7700,7 @@ get_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind) static inline bool is_cxx (void) { - unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); + unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language); return lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus; } @@ -7691,7 +7710,7 @@ is_cxx (void) static inline bool is_fortran (void) { - unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); + unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language); return (lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90 @@ -7703,7 +7722,7 @@ is_fortran (void) static inline bool is_ada (void) { - unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); + unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language); return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83; } @@ -8446,7 +8465,7 @@ DEBUG_FUNCTION void debug_dwarf (void) { print_indent = 0; - print_die (comp_unit_die, stderr); + print_die (comp_unit_die (), stderr); if (! DWARF2_ASM_LINE_DEBUG_INFO) print_dwarf_line_table (stderr); } @@ -9496,6 +9515,14 @@ is_symbol_die (dw_die_ref c) || c->die_tag == DW_TAG_module); } +/* Returns true iff C is a compile-unit DIE. */ + +static inline bool +is_cu_die (dw_die_ref c) +{ + return c && c->die_tag == DW_TAG_compile_unit; +} + static char * gen_internal_sym (const char *prefix) { @@ -10021,7 +10048,7 @@ break_out_comdat_types (dw_die_ref die) add it to the list of comdat types. */ unit = new_die (DW_TAG_type_unit, NULL, NULL); add_AT_unsigned (unit, DW_AT_language, - get_AT_unsigned (comp_unit_die, DW_AT_language)); + get_AT_unsigned (comp_unit_die (), DW_AT_language)); type_node = ggc_alloc_cleared_comdat_type_node (); type_node->root_die = unit; type_node->next = comdat_type_list; @@ -11343,7 +11370,7 @@ add_pubtype (tree decl, dw_die_ref die) e.name = NULL; if ((TREE_PUBLIC (decl) - || die->die_parent == comp_unit_die) + || is_cu_die (die->die_parent)) && (die->die_tag == DW_TAG_typedef || COMPLETE_TYPE_P (decl))) { e.die = die; @@ -12547,7 +12574,7 @@ base_type_die (tree type) gcc_unreachable (); } - base_type_result = new_die (DW_TAG_base_type, comp_unit_die, type); + base_type_result = new_die (DW_TAG_base_type, comp_unit_die (), type); add_AT_unsigned (base_type_result, DW_AT_byte_size, int_size_in_bytes (type)); @@ -12638,7 +12665,7 @@ subrange_type_die (tree type, tree low, tree high, dw_die_ref context_die) const HOST_WIDE_INT size_in_bytes = int_size_in_bytes (type); if (context_die == NULL) - context_die = comp_unit_die; + context_die = comp_unit_die (); subrange_die = new_die (DW_TAG_subrange_type, context_die, type); @@ -12733,17 +12760,17 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type, if (is_const_type) { - mod_type_die = new_die (DW_TAG_const_type, comp_unit_die, type); + mod_type_die = new_die (DW_TAG_const_type, comp_unit_die (), type); sub_die = modified_type_die (type, 0, is_volatile_type, context_die); } else if (is_volatile_type) { - mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die, type); + mod_type_die = new_die (DW_TAG_volatile_type, comp_unit_die (), type); sub_die = modified_type_die (type, 0, 0, context_die); } else if (code == POINTER_TYPE) { - mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type); + mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die (), type); add_AT_unsigned (mod_type_die, DW_AT_byte_size, simple_type_size_in_bits (type) / BITS_PER_UNIT); item_type = TREE_TYPE (type); @@ -12754,10 +12781,10 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type, else if (code == REFERENCE_TYPE) { if (TYPE_REF_IS_RVALUE (type) && dwarf_version >= 4) - mod_type_die = new_die (DW_TAG_rvalue_reference_type, comp_unit_die, + mod_type_die = new_die (DW_TAG_rvalue_reference_type, comp_unit_die (), type); else - mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type); + mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die (), type); add_AT_unsigned (mod_type_die, DW_AT_byte_size, simple_type_size_in_bits (type) / BITS_PER_UNIT); item_type = TREE_TYPE (type); @@ -15921,10 +15948,22 @@ add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind, static void add_accessibility_attribute (dw_die_ref die, tree decl) { + /* In DWARF3+ the default is DW_ACCESS_private only in DW_TAG_class_type + children, otherwise the default is DW_ACCESS_public. In DWARF2 + the default has always been DW_ACCESS_public. */ if (TREE_PROTECTED (decl)) add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected); else if (TREE_PRIVATE (decl)) - add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_private); + { + if (dwarf_version == 2 + || die->die_parent == NULL + || die->die_parent->die_tag != DW_TAG_class_type) + add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_private); + } + else if (dwarf_version > 2 + && die->die_parent + && die->die_parent->die_tag == DW_TAG_class_type) + add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public); } /* Attach the specialized form of location attribute used for data members of @@ -17104,7 +17143,7 @@ add_comp_dir_attribute (dw_die_ref die) static int lower_bound_default (void) { - switch (get_AT_unsigned (comp_unit_die, DW_AT_language)) + switch (get_AT_unsigned (comp_unit_die (), DW_AT_language)) { case DW_LANG_C: case DW_LANG_C89: @@ -17233,7 +17272,7 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree b break; if (current_function_decl == 0) - ctx = comp_unit_die; + ctx = comp_unit_die (); else ctx = lookup_decl_die (current_function_decl); @@ -17426,7 +17465,7 @@ add_bit_size_attribute (dw_die_ref die, tree decl) static inline void add_prototyped_attribute (dw_die_ref die, tree func_type) { - if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89 + if (get_AT_unsigned (comp_unit_die (), DW_AT_language) == DW_LANG_C89 && TYPE_ARG_TYPES (func_type) != NULL) add_AT_flag (die, DW_AT_prototyped, 1); } @@ -17606,17 +17645,17 @@ dwarf2out_vms_debug_main_pointer (void) current_function_funcdef_no); add_AT_lbl_id (die, DW_AT_entry_pc, label); - /* Make it the first child of comp_unit_die. */ - die->die_parent = comp_unit_die; - if (comp_unit_die->die_child) + /* Make it the first child of comp_unit_die (). */ + die->die_parent = comp_unit_die (); + if (comp_unit_die ()->die_child) { - die->die_sib = comp_unit_die->die_child->die_sib; - comp_unit_die->die_child->die_sib = die; + die->die_sib = comp_unit_die ()->die_child->die_sib; + comp_unit_die ()->die_child->die_sib = die; } else { die->die_sib = die; - comp_unit_die->die_child = die; + comp_unit_die ()->die_child = die; } } #endif /* VMS_DEBUGGING_INFO */ @@ -17671,7 +17710,7 @@ scope_die_for (tree t, dw_die_ref context_die) containing_scope = NULL_TREE; if (containing_scope == NULL_TREE) - scope_die = comp_unit_die; + scope_die = comp_unit_die (); else if (TYPE_P (containing_scope)) { /* For types, we can just look up the appropriate DIE. But @@ -17691,7 +17730,7 @@ scope_die_for (tree t, dw_die_ref context_die) /* If none of the current dies are suitable, we get file scope. */ if (scope_die == NULL) - scope_die = comp_unit_die; + scope_die = comp_unit_die (); } else scope_die = lookup_type_die (containing_scope); @@ -18195,7 +18234,7 @@ retry_incomplete_types (void) for (i = VEC_length (tree, incomplete_types) - 1; i >= 0; i--) if (should_emit_struct_debug (VEC_index (tree, incomplete_types, i), DINFO_USAGE_DIR_USE)) - gen_type_die (VEC_index (tree, incomplete_types, i), comp_unit_die); + gen_type_die (VEC_index (tree, incomplete_types, i), comp_unit_die ()); } /* Determine what tag to use for a record type. */ @@ -18565,7 +18604,7 @@ dwarf2out_abstract_function (tree decl) context = decl_class_context (decl); if (context) gen_type_die_for_member - (context, decl, decl_function_context (decl) ? NULL : comp_unit_die); + (context, decl, decl_function_context (decl) ? NULL : comp_unit_die ()); } /* Pretend we've just finished compiling this function. */ @@ -18729,7 +18768,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) instances of inlines, since the spec requires the out-of-line copy to have the same parent. For local class methods, this doesn't apply; we just use the old DIE. */ - if ((old_die->die_parent == comp_unit_die || context_die == NULL) + if ((is_cu_die (old_die->die_parent) || context_die == NULL) && (DECL_ARTIFICIAL (decl) || (get_AT_file (old_die, DW_AT_decl_file) == file_index && (get_AT_unsigned (old_die, DW_AT_decl_line) @@ -19591,6 +19630,38 @@ gen_compile_unit_die (const char *filename) add_AT_string (die, DW_AT_producer, producer); + /* If our producer is LTO try to figure out a common language to use + from the global list of translation units. */ + if (strcmp (language_string, "GNU GIMPLE") == 0) + { + unsigned i; + tree t; + const char *common_lang = NULL; + + FOR_EACH_VEC_ELT (tree, all_translation_units, i, t) + { + if (!TRANSLATION_UNIT_LANGUAGE (t)) + continue; + if (!common_lang) + common_lang = TRANSLATION_UNIT_LANGUAGE (t); + else if (strcmp (common_lang, TRANSLATION_UNIT_LANGUAGE (t)) == 0) + ; + else if (strncmp (common_lang, "GNU C", 5) == 0 + && strncmp (TRANSLATION_UNIT_LANGUAGE (t), "GNU C", 5) == 0) + /* Mixing C and C++ is ok, use C++ in that case. */ + common_lang = "GNU C++"; + else + { + /* Fall back to C. */ + common_lang = NULL; + break; + } + } + + if (common_lang) + language_string = common_lang; + } + language = DW_LANG_C89; if (strcmp (language_string, "GNU C++") == 0) language = DW_LANG_C_plus_plus; @@ -19643,10 +19714,20 @@ gen_inheritance_die (tree binfo, tree access, dw_die_ref context_die) if (BINFO_VIRTUAL_P (binfo)) add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual); + /* In DWARF3+ the default is DW_ACCESS_private only in DW_TAG_class_type + children, otherwise the default is DW_ACCESS_public. In DWARF2 + the default has always been DW_ACCESS_private. */ if (access == access_public_node) - add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public); + { + if (dwarf_version == 2 + || context_die->die_tag == DW_TAG_class_type) + add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public); + } else if (access == access_protected_node) add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected); + else if (dwarf_version > 2 + && context_die->die_tag != DW_TAG_class_type) + add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_private); } /* Generate a DIE for a class member. */ @@ -19740,7 +19821,7 @@ gen_struct_or_union_type_die (tree type, dw_die_ref context_die, scope_die = scope_die_for (type, context_die); - if (! type_die || (nested && scope_die == comp_unit_die)) + if (! type_die || (nested && is_cu_die (scope_die))) /* First occurrence of type or toplevel definition of nested class. */ { dw_die_ref old_die = type_die; @@ -20117,7 +20198,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die, tree name = TYPE_NAME (type); if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); - type_die = new_die (DW_TAG_unspecified_type, comp_unit_die, type); + type_die = new_die (DW_TAG_unspecified_type, comp_unit_die (), type); add_name_attribute (type_die, IDENTIFIER_POINTER (name)); equate_type_number_to_die (type, type_die); } @@ -20347,7 +20428,7 @@ get_context_die (tree context) else return force_decl_die (context); } - return comp_unit_die; + return comp_unit_die (); } /* Returns the DIE for decl. A DIE will always be returned. */ @@ -20393,7 +20474,11 @@ force_decl_die (tree decl) dwarf2out_decl (decl); else /* DWARF2 has neither DW_TAG_module, nor DW_TAG_namespace. */ - decl_die = comp_unit_die; + decl_die = comp_unit_die (); + break; + + case TRANSLATION_UNIT_DECL: + decl_die = comp_unit_die (); break; default: @@ -20490,7 +20575,7 @@ gen_namespace_die (tree decl, dw_die_ref context_die) if (DECL_ABSTRACT_ORIGIN (decl) == NULL) { /* Output a real namespace or module. */ - context_die = setup_namespace_context (decl, comp_unit_die); + context_die = setup_namespace_context (decl, comp_unit_die ()); namespace_die = new_die (is_fortran () ? DW_TAG_module : DW_TAG_namespace, context_die, decl); @@ -20517,7 +20602,7 @@ gen_namespace_die (tree decl, dw_die_ref context_die) if (DECL_CONTEXT (decl) == NULL_TREE || TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL) - context_die = setup_namespace_context (decl, comp_unit_die); + context_die = setup_namespace_context (decl, comp_unit_die ()); /* Now create the namespace alias DIE. */ namespace_die = new_die (DW_TAG_imported_declaration, context_die, decl); add_name_and_src_coords_attributes (namespace_die, decl); @@ -20888,7 +20973,7 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context, void dwarf2out_decl (tree decl) { - dw_die_ref context_die = comp_unit_die; + dw_die_ref context_die = comp_unit_die (); switch (TREE_CODE (decl)) { @@ -20982,16 +21067,7 @@ dwarf2out_decl (tree decl) /* Don't bother trying to generate any DIEs to represent any of the normal built-in types for the language we are compiling. */ if (DECL_IS_BUILTIN (decl)) - { - /* OK, we need to generate one for `bool' so GDB knows what type - comparisons have. */ - if (is_cxx () - && TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE - && ! DECL_IGNORED_P (decl)) - modified_type_die (TREE_TYPE (decl), 0, 0, NULL); - - return; - } + return; /* If we are in terse mode, don't generate any DIEs for types. */ if (debug_info_level <= DINFO_LEVEL_TERSE) @@ -21542,7 +21618,7 @@ dwarf2out_start_source_file (unsigned int lineno, const char *filename) /* Record the beginning of the file for break_out_includes. */ dw_die_ref bincl_die; - bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL); + bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die (), NULL); add_AT_string (bincl_die, DW_AT_name, remap_debug_filename (filename)); } @@ -21566,7 +21642,7 @@ dwarf2out_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED) { if (flag_eliminate_dwarf2_dups && dwarf_version < 4) /* Record the end of the file for break_out_includes. */ - new_die (DW_TAG_GNU_EINCL, comp_unit_die, NULL); + new_die (DW_TAG_GNU_EINCL, comp_unit_die (), NULL); if (debug_info_level >= DINFO_LEVEL_VERBOSE) { @@ -21652,14 +21728,6 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED) vcall_insn_table = htab_create_ggc (10, vcall_insn_table_hash, vcall_insn_table_eq, NULL); - /* Generate the initial DIE for the .debug section. Note that the (string) - value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE - will (typically) be a relative pathname and that this pathname should be - taken as being relative to the directory from which the compiler was - invoked when the given (base) source file was compiled. We will fill - in this value in dwarf2out_finish. */ - comp_unit_die = gen_compile_unit_die (NULL); - incomplete_types = VEC_alloc (tree, gc, 64); used_rtx_array = VEC_alloc (rtx, gc, 32); @@ -22069,7 +22137,7 @@ prune_unused_types (void) #if ENABLE_ASSERT_CHECKING /* All the marks should already be clear. */ - verify_marks_clear (comp_unit_die); + verify_marks_clear (comp_unit_die ()); for (node = limbo_die_list; node; node = node->next) verify_marks_clear (node->die); for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next) @@ -22080,7 +22148,7 @@ prune_unused_types (void) premark_types_used_by_global_vars (); /* Set the mark on nodes that are actually used. */ - prune_unused_types_walk (comp_unit_die); + prune_unused_types_walk (comp_unit_die ()); for (node = limbo_die_list; node; node = node->next) prune_unused_types_walk (node->die); for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next) @@ -22105,14 +22173,14 @@ prune_unused_types (void) htab_traverse (debug_str_hash, prune_indirect_string, NULL); else if (debug_str_hash) htab_empty (debug_str_hash); - prune_unused_types_prune (comp_unit_die); + prune_unused_types_prune (comp_unit_die ()); for (node = limbo_die_list; node; node = node->next) prune_unused_types_prune (node->die); for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next) prune_unused_types_prune (ctnode->root_die); /* Leave the marks clear. */ - prune_unmark_dies (comp_unit_die); + prune_unmark_dies (comp_unit_die ()); for (node = limbo_die_list; node; node = node->next) prune_unmark_dies (node->die); for (ctnode = comdat_type_list; ctnode; ctnode = ctnode->next) @@ -22331,15 +22399,15 @@ dwarf2out_finish (const char *filename) /* Add the name for the main input file now. We delayed this from dwarf2out_init to avoid complications with PCH. */ - add_name_attribute (comp_unit_die, remap_debug_filename (filename)); + add_name_attribute (comp_unit_die (), remap_debug_filename (filename)); if (!IS_ABSOLUTE_PATH (filename)) - add_comp_dir_attribute (comp_unit_die); - else if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL) + add_comp_dir_attribute (comp_unit_die ()); + else if (get_AT (comp_unit_die (), DW_AT_comp_dir) == NULL) { bool p = false; htab_traverse (file_table, file_table_relative_p, &p); if (p) - add_comp_dir_attribute (comp_unit_die); + add_comp_dir_attribute (comp_unit_die ()); } for (i = 0; i < VEC_length (deferred_locations, deferred_locations_list); i++) @@ -22366,11 +22434,11 @@ dwarf2out_finish (const char *filename) if (origin) add_child_die (origin->die_parent, die); - else if (die == comp_unit_die) + else if (is_cu_die (die)) ; else if (seen_error ()) /* It's OK to be confused by errors in the input. */ - add_child_die (comp_unit_die, die); + add_child_die (comp_unit_die (), die); else { /* In certain situations, the lexical block containing a @@ -22400,14 +22468,14 @@ dwarf2out_finish (const char *filename) if (origin) add_child_die (origin, die); else - add_child_die (comp_unit_die, die); + add_child_die (comp_unit_die (), die); } } } limbo_die_list = NULL; - resolve_addr (comp_unit_die); + resolve_addr (comp_unit_die ()); for (node = deferred_asm_name; node; node = node->next) { @@ -22431,12 +22499,12 @@ dwarf2out_finish (const char *filename) /* Generate separate CUs for each of the include files we've seen. They will go into limbo_die_list. */ if (flag_eliminate_dwarf2_dups && dwarf_version < 4) - break_out_includes (comp_unit_die); + break_out_includes (comp_unit_die ()); /* Generate separate COMDAT sections for type DIEs. */ if (dwarf_version >= 4) { - break_out_comdat_types (comp_unit_die); + break_out_comdat_types (comp_unit_die ()); /* Each new type_unit DIE was added to the limbo die list when created. Since these have all been added to comdat_type_list, clear the @@ -22448,7 +22516,7 @@ dwarf2out_finish (const char *filename) references to the main compile unit). */ for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next) copy_decls_for_unworthy_types (ctnode->root_die); - copy_decls_for_unworthy_types (comp_unit_die); + copy_decls_for_unworthy_types (comp_unit_die ()); /* In the process of copying declarations from one unit to another, we may have left some declarations behind that are no longer @@ -22458,7 +22526,7 @@ dwarf2out_finish (const char *filename) /* Traverse the DIE's and add add sibling attributes to those DIE's that have children. */ - add_sibling_attributes (comp_unit_die); + add_sibling_attributes (comp_unit_die ()); for (node = limbo_die_list; node; node = node->next) add_sibling_attributes (node->die); for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next) @@ -22478,8 +22546,8 @@ dwarf2out_finish (const char *filename) if (!have_multiple_function_sections || !(dwarf_version >= 3 || !dwarf_strict)) { - add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label); - add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label); + add_AT_lbl_id (comp_unit_die (), DW_AT_low_pc, text_section_label); + add_AT_lbl_id (comp_unit_die (), DW_AT_high_pc, text_end_label); } else @@ -22492,14 +22560,14 @@ dwarf2out_finish (const char *filename) absolute. Historically, we've emitted the unexpected DW_AT_entry_pc instead of DW_AT_low_pc for this purpose. Emit both to give time for other tools to adapt. */ - add_AT_addr (comp_unit_die, DW_AT_low_pc, const0_rtx); - add_AT_addr (comp_unit_die, DW_AT_entry_pc, const0_rtx); + add_AT_addr (comp_unit_die (), DW_AT_low_pc, const0_rtx); + add_AT_addr (comp_unit_die (), DW_AT_entry_pc, const0_rtx); if (text_section_used) - add_ranges_by_labels (comp_unit_die, text_section_label, + add_ranges_by_labels (comp_unit_die (), text_section_label, text_end_label, &range_list_added); if (flag_reorder_blocks_and_partition && cold_text_section_used) - add_ranges_by_labels (comp_unit_die, cold_text_section_label, + add_ranges_by_labels (comp_unit_die (), cold_text_section_label, cold_end_label, &range_list_added); for (fde_idx = 0; fde_idx < fde_table_in_use; fde_idx++) @@ -22509,18 +22577,18 @@ dwarf2out_finish (const char *filename) if (fde->dw_fde_switched_sections) { if (!fde->in_std_section) - add_ranges_by_labels (comp_unit_die, + add_ranges_by_labels (comp_unit_die (), fde->dw_fde_hot_section_label, fde->dw_fde_hot_section_end_label, &range_list_added); if (!fde->cold_in_std_section) - add_ranges_by_labels (comp_unit_die, + add_ranges_by_labels (comp_unit_die (), fde->dw_fde_unlikely_section_label, fde->dw_fde_unlikely_section_end_label, &range_list_added); } else if (!fde->in_std_section) - add_ranges_by_labels (comp_unit_die, fde->dw_fde_begin, + add_ranges_by_labels (comp_unit_die (), fde->dw_fde_begin, fde->dw_fde_end, &range_list_added); } @@ -22529,11 +22597,11 @@ dwarf2out_finish (const char *filename) } if (debug_info_level >= DINFO_LEVEL_NORMAL) - add_AT_lineptr (comp_unit_die, DW_AT_stmt_list, + add_AT_lineptr (comp_unit_die (), DW_AT_stmt_list, debug_line_section_label); if (debug_info_level >= DINFO_LEVEL_VERBOSE) - add_AT_macptr (comp_unit_die, DW_AT_macro_info, macinfo_section_label); + add_AT_macptr (comp_unit_die (), DW_AT_macro_info, macinfo_section_label); /* Output all of the compilation units. We put the main one last so that the offsets are available to output_pubnames. */ @@ -22563,7 +22631,7 @@ dwarf2out_finish (const char *filename) /* Output the main compilation unit if non-empty or if .debug_macinfo has been emitted. */ - output_comp_unit (comp_unit_die, debug_info_level >= DINFO_LEVEL_VERBOSE); + output_comp_unit (comp_unit_die (), debug_info_level >= DINFO_LEVEL_VERBOSE); /* Output the abbreviation table. */ switch_to_section (debug_abbrev_section); diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index e0e1550948f..35a4360c973 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -5376,6 +5376,8 @@ init_virtual_regs (void) regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx; regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx; regno_reg_rtx[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx; + regno_reg_rtx[VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM] + = virtual_preferred_stack_boundary_rtx; } @@ -5698,6 +5700,8 @@ init_emit_regs (void) virtual_outgoing_args_rtx = gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM); virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM); + virtual_preferred_stack_boundary_rtx = + gen_raw_REG (Pmode, VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM); /* Initialize RTL for commonly used hard registers. These are copied into regno_reg_rtx as we begin to compile each function. */ diff --git a/gcc/explow.c b/gcc/explow.c index 74f52279e54..2024b5324d8 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -915,30 +915,47 @@ anti_adjust_stack (rtx adjust) static rtx round_push (rtx size) { - int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; + rtx align_rtx, alignm1_rtx; - if (align == 1) - return size; - - if (CONST_INT_P (size)) + if (!SUPPORTS_STACK_ALIGNMENT + || crtl->preferred_stack_boundary == MAX_SUPPORTED_STACK_ALIGNMENT) { - HOST_WIDE_INT new_size = (INTVAL (size) + align - 1) / align * align; + int align = crtl->preferred_stack_boundary / BITS_PER_UNIT; + + if (align == 1) + return size; + + if (CONST_INT_P (size)) + { + HOST_WIDE_INT new_size = (INTVAL (size) + align - 1) / align * align; - if (INTVAL (size) != new_size) - size = GEN_INT (new_size); + if (INTVAL (size) != new_size) + size = GEN_INT (new_size); + return size; + } + + align_rtx = GEN_INT (align); + alignm1_rtx = GEN_INT (align - 1); } else { - /* CEIL_DIV_EXPR needs to worry about the addition overflowing, - but we know it can't. So add ourselves and then do - TRUNC_DIV_EXPR. */ - size = expand_binop (Pmode, add_optab, size, GEN_INT (align - 1), - NULL_RTX, 1, OPTAB_LIB_WIDEN); - size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size, GEN_INT (align), - NULL_RTX, 1); - size = expand_mult (Pmode, size, GEN_INT (align), NULL_RTX, 1); + /* If crtl->preferred_stack_boundary might still grow, use + virtual_preferred_stack_boundary_rtx instead. This will be + substituted by the right value in vregs pass and optimized + during combine. */ + align_rtx = virtual_preferred_stack_boundary_rtx; + alignm1_rtx = force_operand (plus_constant (align_rtx, -1), NULL_RTX); } + /* CEIL_DIV_EXPR needs to worry about the addition overflowing, + but we know it can't. So add ourselves and then do + TRUNC_DIV_EXPR. */ + size = expand_binop (Pmode, add_optab, size, alignm1_rtx, + NULL_RTX, 1, OPTAB_LIB_WIDEN); + size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size, align_rtx, + NULL_RTX, 1); + size = expand_mult (Pmode, size, align_rtx, NULL_RTX, 1); + return size; } @@ -1144,9 +1161,9 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align, introduced later by the various alignment operations. */ if (flag_stack_usage) { - if (GET_CODE (size) == CONST_INT) + if (CONST_INT_P (size)) stack_usage_size = INTVAL (size); - else if (GET_CODE (size) == REG) + else if (REG_P (size)) { /* Look into the last emitted insn and see if we can deduce something for the register. */ @@ -1154,10 +1171,10 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align, insn = get_last_insn (); if ((set = single_set (insn)) && rtx_equal_p (SET_DEST (set), size)) { - if (GET_CODE (SET_SRC (set)) == CONST_INT) + if (CONST_INT_P (SET_SRC (set))) stack_usage_size = INTVAL (SET_SRC (set)); else if ((note = find_reg_equal_equiv_note (insn)) - && GET_CODE (XEXP (note, 0)) == CONST_INT) + && CONST_INT_P (XEXP (note, 0))) stack_usage_size = INTVAL (XEXP (note, 0)); } } @@ -1177,7 +1194,8 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align, /* We can't attempt to minimize alignment necessary, because we don't know the final value of preferred_stack_boundary yet while executing this code. */ - crtl->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY; + if (crtl->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY) + crtl->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY; /* We will need to ensure that the address we return is aligned to BIGGEST_ALIGNMENT. If STACK_DYNAMIC_OFFSET is defined, we don't @@ -1195,7 +1213,7 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align, #if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET) #define MUST_ALIGN 1 #else -#define MUST_ALIGN (PREFERRED_STACK_BOUNDARY < BIGGEST_ALIGNMENT) +#define MUST_ALIGN (crtl->preferred_stack_boundary < BIGGEST_ALIGNMENT) #endif if (MUST_ALIGN) @@ -1255,13 +1273,13 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align, insns. Since this is an extremely rare event, we have no reliable way of knowing which systems have this problem. So we avoid even momentarily mis-aligning the stack. */ - if (!known_align_valid || known_align % PREFERRED_STACK_BOUNDARY != 0) + if (!known_align_valid || known_align % MAX_SUPPORTED_STACK_ALIGNMENT != 0) { size = round_push (size); if (flag_stack_usage) { - int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; + int align = crtl->preferred_stack_boundary / BITS_PER_UNIT; stack_usage_size = (stack_usage_size + align - 1) / align * align; } } @@ -1328,6 +1346,8 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align, else #endif { + int saved_stack_pointer_delta; + #ifndef STACK_GROWS_DOWNWARD emit_move_insn (target, virtual_stack_dynamic_rtx); #endif @@ -1358,10 +1378,15 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align, emit_label (space_available); } + saved_stack_pointer_delta = stack_pointer_delta; if (flag_stack_check && STACK_CHECK_MOVING_SP) anti_adjust_stack_and_probe (size, false); else anti_adjust_stack (size); + /* Even if size is constant, don't modify stack_pointer_delta. + The constant size alloca should preserve + crtl->preferred_stack_boundary alignment. */ + stack_pointer_delta = saved_stack_pointer_delta; #ifdef STACK_GROWS_DOWNWARD emit_move_insn (target, virtual_stack_dynamic_rtx); @@ -1572,7 +1597,7 @@ probe_stack_range (HOST_WIDE_INT first, rtx size) { rtx addr; - if (GET_CODE (temp) == CONST_INT) + if (CONST_INT_P (temp)) { /* Use [base + disp} addressing mode if supported. */ HOST_WIDE_INT offset = INTVAL (temp); @@ -1613,7 +1638,7 @@ anti_adjust_stack_and_probe (rtx size, bool adjust_back) /* If we have a constant small number of probes to generate, that's the easy case. */ - if (GET_CODE (size) == CONST_INT && INTVAL (size) < 7 * PROBE_INTERVAL) + if (CONST_INT_P (size) && INTVAL (size) < 7 * PROBE_INTERVAL) { HOST_WIDE_INT isize = INTVAL (size), i; bool first_probe = true; diff --git a/gcc/expr.c b/gcc/expr.c index 16daddc370f..d63ee55e8aa 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -8830,7 +8830,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array) && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array) && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK - && targetm.binds_local_p (array)) + && const_value_known_p (array)) { if (TREE_CODE (index) == INTEGER_CST) { @@ -9381,7 +9381,15 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, { if (GET_CODE (op0) == SUBREG) op0 = force_reg (GET_MODE (op0), op0); - op0 = gen_lowpart (mode, op0); + temp = gen_lowpart_common (mode, op0); + if (temp) + op0 = temp; + else + { + if (!REG_P (op0) && !MEM_P (op0)) + op0 = force_reg (GET_MODE (op0), op0); + op0 = gen_lowpart (mode, op0); + } } /* If both types are integral, convert from one mode to the other. */ else if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (treeop0))) @@ -9846,21 +9854,17 @@ string_constant (tree arg, tree *ptr_offset) *ptr_offset = fold_convert (sizetype, offset); return array; } - else if (TREE_CODE (array) == VAR_DECL) + else if (TREE_CODE (array) == VAR_DECL + || TREE_CODE (array) == CONST_DECL) { int length; /* Variables initialized to string literals can be handled too. */ - if (DECL_INITIAL (array) == NULL_TREE + if (!const_value_known_p (array) + || !DECL_INITIAL (array) || TREE_CODE (DECL_INITIAL (array)) != STRING_CST) return 0; - /* If they are read-only, non-volatile and bind locally. */ - if (! TREE_READONLY (array) - || TREE_SIDE_EFFECTS (array) - || ! targetm.binds_local_p (array)) - return 0; - /* Avoid const char foo[4] = "abcde"; */ if (DECL_SIZE_UNIT (array) == NULL_TREE || TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST diff --git a/gcc/final.c b/gcc/final.c index 79cd85e735c..4fe1031458c 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -4441,7 +4441,10 @@ rest_of_clean_state (void) delete_tree_ssa (); - if (targetm.binds_local_p (current_function_decl)) + /* We can reduce stack alignment on call site only when we are sure that + the function body just produced will be actually used in the final + executable. */ + if (decl_binds_to_current_def_p (current_function_decl)) { unsigned int pref = crtl->preferred_stack_boundary; if (crtl->stack_alignment_needed > crtl->preferred_stack_boundary) diff --git a/gcc/flags.h b/gcc/flags.h index 93221b4409c..805308cf984 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -164,11 +164,6 @@ extern int rtl_dump_and_exit; extern int flag_gen_aux_info; -/* Nonzero means suppress output of instruction numbers and line number - notes in debugging dumps. */ - -extern int flag_dump_unnumbered; - /* True if printing into -fdump-final-insns= dump. */ extern bool final_insns_dump_p; @@ -301,9 +296,6 @@ enum graph_dump_types }; extern enum graph_dump_types graph_dump_format; -/* Nonzero if we should track variables. */ -extern int flag_var_tracking; - /* True if flag_speculative_prefetching was set by user. Used to suppress warning message in case flag was set by -fprofile-{generate,use}. */ extern bool flag_speculative_prefetching_set; diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 966287d91a0..b04f3c50419 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,228 @@ +2010-09-27 Tobias Burnus <burnus@net-b.de> + + PR fortran/40569 + PR fortran/40568 + * intrinsic.h (gfc_simplify_compiler_options, + gfc_simplify_compiler_version): New prototypes. + * intrinsic.c (gfc_intrinsic_function_by_id, + make_from_module): New functions. + (gfc_find_function, gfc_find_subroutine, gfc_generic_intrinsic, + gfc_specific_intrinsic): Don't return module intrinsics. + (add_functions): Add compiler_options, compiler_version. + (gfc_intrinsic_func_interface): Also lookup symbol by ISYM ID. + * symbol.c (std_for_isocbinding_symbol): Add version check for + NAMED_FUNCTIONS. + * iso-fortran-env.def: Add compiler_options, compiler_version. + * iso-c-binding.def: Add c_sizeof. + * gfortran.h (gfc_intrinsic_sym): Add from_module:1. + (iso_c_binding_symbol, iso_fortran_env_symbol): Add NAMED_FUNCTIONS. + (gfc_intrinsic_function_by_id): New prototype. + * module.c (create_intrinsic_function): New function. + (import_iso_c_binding_module, use_iso_fortran_env_module): Use it. + * trans-types.c (init_c_interop_kinds): Add NAMED_FUNCTIONS. + * resolve.c (resolve_intrinsic): Try also to resolve intrinsics + by ISYM ID. + * simplify.c (gfc_simplify_compiler_options, + gfc_simplify_compiler_version): New functions. + +2010-09-26 Daniel Kraft <d@domob.eu> + + PR fortran/45783 + PR fortran/45795 + * resolve.c (resolve_select_type): Clarify code. + (resolve_assoc_var): Only set typespec if it is currently unknown. + +2010-09-26 Jerry DeLisle <jvdelisle@gcc.gnu.org> + + PR fortran/45793 + * module.c (create_int_parameter_array): Set the array value shape. + +2010-09-25 Tobias Burnus <burnus@net-b.de> + + * gfortran.texi: Re-add accidently removed \input line. + +2010-09-25 Daniel Kraft <d@domob.eu> + + PR fortran/45776 + * gfortran.h (struct gfc_dt): New member `dt_io_kind'. + * io.c (resolve_tag): F2008 check for NEWUNIT and variable + definition checks for NEWUNIT, IOSTAT, SIZE and IOMSG. + (gfc_free_dt): Correctly handle freeing of `dt_io_kind' and + `extra_comma' with changed semantics. + (gfc_resolve_dt): Check variable definitions. + (match_io_element): Remove INTENT and PURE checks here and + initialize code->ext.dt member. + (match_io): Set dt->dt_io_kind. + (gfc_resolve_inquire): Check variable definition for all tags + except UNIT, FILE and ID. + * resolve.c (resolve_transfer): Variable definition check. + +2010-09-25 Tobias Burnus <burnus@net-b.de> + + * interface.c (gfc_match_end_interface): Constify char pointer + to fix warning. + +2010-09-24 Steven G. Kargl < kargl@gcc.gnu.org> + + * interface.c (gfc_match_end_interface): Deal with user defined + operators that overload rational operators and C1202. + +2010-09-24 Tobias Burnus <burnus@net-b.de> + + * gfortran.texi: Add second space after end-of-sentence period; + change / to /@/ to allow hyphenation of URLs. + (Standards): Remove duplicated OpenMP, update wording given that + Fortran 2008 now released. + (Fortran 2008 status): Update and add list of implemented features. + +2010-09-24 Tobias Burnus <burnus@net-b.de> + + PR fortran/40571 + * iso-fortran-env.def: Add NAMED_KINDARRAY with + character_kinds, integer_kinds, logical_kinds and + real_kinds. + * gfortran.h: Add them to iso_fortran_env_symbol. + * libgfortran.h: Rename GFC_INQUIRE_INTERNAL_UNIT to + LIBERROR_INQUIRE_INTERNAL_UNIT and move it from + libgfortran_stat_codes to libgfortran_error_codes. + * module.c (create_int_parameter_array): New function. + (use_iso_fortran_env_module): Use it for + NAMED_KINDARRAY of iso-fortran-env.def. + * trans-decl.c (gfc_get_symbol_decl): Parameter + arrays of intrinsics modules become local static variables. + * intrinsic.texi (ISO_FORTRAN_ENV): Add character_kinds, + integer_kinds, logical_kinds and real_kinds. + +2010-09-23 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/45744 + * frontend-passes.c (optimize_binop_array_assignment): + Only re-use lhs as intermediate storage if kind and type + parameters match. + +2010-09-23 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/45745 + PR fortran/45648 + * trans-array.c (gfc_conv_expr_descriptor): Handle + ss->type == GFC_SS_INTRINSIC (for {l,u}bound intrinsics) case. + +2010-09-23 Tobias Burnus <burnus@net-b.de> + + * intrinsic.texi (OpenMP modules): Add named constants of + OMP_LIB. + +2010-09-23 Daniel Kraft <d@domob.eu> + + PR fortran/38936 + PR fortran/44044 + PR fortran/45474 + * gfortran.h (gfc_check_vardef_context): New method. + (struct symbol_attribute): New flag `select_type_temporary'. + * primary.c (gfc_variable_attr): Clarify initialization of ref. + (match_variable): Remove PROTECTED check and assignment check + for PARAMETERs (this is now done later). + * match.c (gfc_match_iterator): Remove INTENT(IN) check. + (gfc_match_associate): Defer initialization of newAssoc->variable. + (gfc_match_nullify): Remove PURE definability check. + (select_type_set_tmp): Set new `select_type_temporary' flag. + * expr.c (gfc_check_assign): Remove INTENT(IN) check here. + (gfc_check_pointer_assign): Ditto (and other checks removed). + (gfc_check_vardef_context): New method. + * interface.c (compare_parameter_protected): Removed. + (compare_actual_formal): Use `gfc_check_vardef_context' for checks + related to INTENT([IN]OUT) arguments. + * intrinsic.c (check_arglist): Check INTENT for intrinsics. + * resolve.c (gfc_resolve_iterator): Use `gfc_check_vardef_context'. + (remove_last_array_ref): New method. + (resolve_deallocate_expr), (resolve_allocate_expr): Ditto. + (resolve_allocate_deallocate): Ditto (for STAT and ERRMSG). + (resolve_assoc_var): Remove checks for definability here. + (resolve_select_type): Handle resolving of code->block here. + (resolve_ordinary_assign): Remove PURE check. + (resolve_code): Do not resolve code->blocks for SELECT TYPE here. + Use `gfc_check_vardef_context' for assignments and pointer-assignments. + +2010-08-22 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * gfortran.texi (Argument list functions): Allow URL to wrap. + * intrinsic.texi (GETGID, GETPID, GETUID, IMAGE_INDEX) + (IS_IOSTAT_END, IS_IOSTAT_EOR, NUM_IMAGES, THIS_IMAGE) + (ISO_FORTRAN_ENV): Fix markup in index entries, and a couple of + code markups in the text. + * invoke.texi (Fortran Dialect Options) + (Error and Warning Options, Directory Options, Code Gen Options): + Likewise. Remove @code inside @smallexample. + +2010-09-22 Joseph Myers <joseph@codesourcery.com> + + * gfortranspec.c (lang_specific_driver): Handle OPT__version and + OPT__help instead of OPT_fversion and OPT_fhelp. + * lang.opt (-all-warnings, -assert, -assert=, -comments, + -comments-in-macros, -define-macro, -define-macro=, -dependencies, + -dump, -dump=, -include-barrier, -include-directory, + -include-directory=, -include-directory-after, + -include-directory-after=, -include-prefix, -include-prefix=, + -no-line-commands, -no-standard-includes, -output, -output=, + -preprocess, -print-missing-file-dependencies, -trace-includes, + -undefine-macro, -undefine-macro=, -user-dependencies, -verbose, + -write-dependencies, -write-user-dependencies): New. + +2010-09-21 Jason Blevins <jrblevin@sdf.org> + + * intrinsics.texi (HYPOT, IMAGE_INDEX, BESSEL_JN, BESSEL_YN, + execute_command_line, IEOR, IOR, NORM2, NOT, NULL, PARITY): + Correct spelling. + +2010-09-21 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/45648 + * trans-array.c (gfc_conv_expr_descriptor): Calculate dim out of n and + info->dim. + + PR fortran/45648 + * trans-array.c (gfc_conv_expr_descriptor): Unset full if we are + accessing dimensions in reversed order. + + PR fortran/45648 + * trans-array.c (gfc_conv_expr_descriptor): Special case noncopying + intrinsic function call. + + * trans-array.c (gfc_conv_expr_descriptor): Remove ss lookup. + Update asserts accordingly. + + PR fortran/45648 + * trans.h (gfc_se): New field force_tmp. + * trans-expr.c (gfc_conv_procedure_call): Check for argument alias + and set parmse.force_tmp if some alias is found. + * trans-array.c (gfc_conv_expr_descriptor): Force a temporary creation + if se->force_tmp is set. + +2010-09-20 Janus Weil <janus@gcc.gnu.org> + + PR fortran/45438 + * trans-expr.c (gfc_conv_procedure_call): Fix pointer checking for + TBPs, PPCs and pointer/allocatable components. + +2010-09-20 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/45081 + * simplify.c (is_constant_array_expr): Allow structure array + elements as well as constants. + (gfc_simplify_pack, gfc_simplify_reshape, gfc_simplify_spread, + gfc_simplify_transpose, gfc_simplify_unpack): Copy the derived + type of source to the result. + +2010-09-19 Thomas Koenig <tkoenig@gcc.gnu.org> + + * frontend-passes.c (gfc_expr_walker): Also + handle EXPR_SUBSTRING. + +2010-09-19 Thomas Koenig <tkoenig@gcc.gnu.org> + + * frontend-passes.c (gfc_expr_walker): Handle + constructors and references. + 2010-09-16 Tobias Burnus <burnus@net-b.de> PR fortran/43665 diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 76ceec95715..57116344666 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -3043,10 +3043,8 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform) sym = lvalue->symtree->n.sym; - /* Check INTENT(IN), unless the object itself is the component or - sub-component of a pointer. */ + /* See if this is the component or subcomponent of a pointer. */ has_pointer = sym->attr.pointer; - for (ref = lvalue->ref; ref; ref = ref->next) if (ref->type == REF_COMPONENT && ref->u.c.component->attr.pointer) { @@ -3054,13 +3052,6 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform) break; } - if (!has_pointer && sym->attr.intent == INTENT_IN) - { - gfc_error ("Cannot assign to INTENT(IN) variable '%s' at %L", - sym->name, &lvalue->where); - return FAILURE; - } - /* 12.5.2.2, Note 12.26: The result variable is very similar to any other variable local to a function subprogram. Its existence begins when execution of the function is initiated and ends when execution of the @@ -3239,7 +3230,7 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue) symbol_attribute attr; gfc_ref *ref; bool is_pure, rank_remap; - int pointer, check_intent_in, proc_pointer; + int proc_pointer; if (lvalue->symtree->n.sym->ts.type == BT_UNKNOWN && !lvalue->symtree->n.sym->attr.proc_pointer) @@ -3259,24 +3250,13 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue) return FAILURE; } - - /* 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; proc_pointer = lvalue->symtree->n.sym->attr.proc_pointer; rank_remap = false; for (ref = lvalue->ref; ref; ref = ref->next) { - if (pointer) - check_intent_in = 0; - if (ref->type == REF_COMPONENT) - { - pointer = ref->u.c.component->attr.pointer; - proc_pointer = ref->u.c.component->attr.proc_pointer; - } + proc_pointer = ref->u.c.component->attr.proc_pointer; if (ref->type == REF_ARRAY && ref->next == NULL) { @@ -3332,30 +3312,8 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue) } } - if (check_intent_in && lvalue->symtree->n.sym->attr.intent == INTENT_IN) - { - gfc_error ("Cannot assign to INTENT(IN) variable '%s' at %L", - lvalue->symtree->n.sym->name, &lvalue->where); - return FAILURE; - } - - if (!pointer && !proc_pointer - && !(lvalue->ts.type == BT_CLASS - && CLASS_DATA (lvalue)->attr.class_pointer)) - { - gfc_error ("Pointer assignment to non-POINTER at %L", &lvalue->where); - return FAILURE; - } - is_pure = gfc_pure (NULL); - if (is_pure && gfc_impure_variable (lvalue->symtree->n.sym) - && lvalue->symtree->n.sym->value != rvalue) - { - gfc_error ("Bad pointer object in PURE procedure at %L", &lvalue->where); - return FAILURE; - } - /* If rvalue is a NULL() or NULLIFY, we're done. Otherwise the type, kind, etc for lvalue and rvalue must match, and rvalue must be a pure variable if we're in a pure function. */ @@ -4338,3 +4296,188 @@ gfc_build_intrinsic_call (const char* name, locus where, unsigned numarg, ...) return result; } + + +/* Check if an expression may appear in a variable definition context + (F2008, 16.6.7) or pointer association context (F2008, 16.6.8). + This is called from the various places when resolving + the pieces that make up such a context. + + Optionally, a possible error message can be suppressed if context is NULL + and just the return status (SUCCESS / FAILURE) be requested. */ + +gfc_try +gfc_check_vardef_context (gfc_expr* e, bool pointer, const char* context) +{ + gfc_symbol* sym; + bool is_pointer; + bool check_intentin; + bool ptr_component; + symbol_attribute attr; + gfc_ref* ref; + + if (e->expr_type != EXPR_VARIABLE) + { + if (context) + gfc_error ("Non-variable expression in variable definition context (%s)" + " at %L", context, &e->where); + return FAILURE; + } + + gcc_assert (e->symtree); + sym = e->symtree->n.sym; + + if (!pointer && sym->attr.flavor == FL_PARAMETER) + { + if (context) + gfc_error ("Named constant '%s' in variable definition context (%s)" + " at %L", sym->name, context, &e->where); + return FAILURE; + } + if (!pointer && sym->attr.flavor != FL_VARIABLE + && !(sym->attr.flavor == FL_PROCEDURE && sym == sym->result) + && !(sym->attr.flavor == FL_PROCEDURE && sym->attr.proc_pointer)) + { + if (context) + gfc_error ("'%s' in variable definition context (%s) at %L is not" + " a variable", sym->name, context, &e->where); + return FAILURE; + } + + /* Find out whether the expr is a pointer; this also means following + component references to the last one. */ + attr = gfc_expr_attr (e); + is_pointer = (attr.pointer || attr.proc_pointer); + if (pointer && !is_pointer) + { + if (context) + gfc_error ("Non-POINTER in pointer association context (%s)" + " at %L", context, &e->where); + return FAILURE; + } + + /* INTENT(IN) dummy argument. Check this, unless the object itself is + the component of sub-component of a pointer. Obviously, + procedure pointers are of no interest here. */ + check_intentin = true; + ptr_component = sym->attr.pointer; + for (ref = e->ref; ref && check_intentin; ref = ref->next) + { + if (ptr_component && ref->type == REF_COMPONENT) + check_intentin = false; + if (ref->type == REF_COMPONENT && ref->u.c.component->attr.pointer) + ptr_component = true; + } + if (check_intentin && sym->attr.intent == INTENT_IN) + { + if (pointer && is_pointer) + { + if (context) + gfc_error ("Dummy argument '%s' with INTENT(IN) in pointer" + " association context (%s) at %L", + sym->name, context, &e->where); + return FAILURE; + } + if (!pointer && !is_pointer) + { + if (context) + gfc_error ("Dummy argument '%s' with INTENT(IN) in variable" + " definition context (%s) at %L", + sym->name, context, &e->where); + return FAILURE; + } + } + + /* PROTECTED and use-associated. */ + if (sym->attr.is_protected && sym->attr.use_assoc) + { + if (pointer && is_pointer) + { + if (context) + gfc_error ("Variable '%s' is PROTECTED and can not appear in a" + " pointer association context (%s) at %L", + sym->name, context, &e->where); + return FAILURE; + } + if (!pointer && !is_pointer) + { + if (context) + gfc_error ("Variable '%s' is PROTECTED and can not appear in a" + " variable definition context (%s) at %L", + sym->name, context, &e->where); + return FAILURE; + } + } + + /* Variable not assignable from a PURE procedure but appears in + variable definition context. */ + if (!pointer && gfc_pure (NULL) && gfc_impure_variable (sym)) + { + if (context) + gfc_error ("Variable '%s' can not appear in a variable definition" + " context (%s) at %L in PURE procedure", + sym->name, context, &e->where); + return FAILURE; + } + + /* Check variable definition context for associate-names. */ + if (!pointer && sym->assoc) + { + const char* name; + gfc_association_list* assoc; + + gcc_assert (sym->assoc->target); + + /* If this is a SELECT TYPE temporary (the association is used internally + for SELECT TYPE), silently go over to the target. */ + if (sym->attr.select_type_temporary) + { + gfc_expr* t = sym->assoc->target; + + gcc_assert (t->expr_type == EXPR_VARIABLE); + name = t->symtree->name; + + if (t->symtree->n.sym->assoc) + assoc = t->symtree->n.sym->assoc; + else + assoc = sym->assoc; + } + else + { + name = sym->name; + assoc = sym->assoc; + } + gcc_assert (name && assoc); + + /* Is association to a valid variable? */ + if (!assoc->variable) + { + if (context) + { + if (assoc->target->expr_type == EXPR_VARIABLE) + gfc_error ("'%s' at %L associated to vector-indexed target can" + " not be used in a variable definition context (%s)", + name, &e->where, context); + else + gfc_error ("'%s' at %L associated to expression can" + " not be used in a variable definition context (%s)", + name, &e->where, context); + } + return FAILURE; + } + + /* Target must be allowed to appear in a variable definition context. */ + if (gfc_check_vardef_context (assoc->target, pointer, NULL) == FAILURE) + { + if (context) + gfc_error ("Associate-name '%s' can not appear in a variable" + " definition context (%s) at %L because its target" + " at %L can not, either", + name, context, &e->where, + &assoc->target->where); + return FAILURE; + } + } + + return SUCCESS; +} diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c index b6a74fd2cce..aefee62808b 100644 --- a/gcc/fortran/frontend-passes.c +++ b/gcc/fortran/frontend-passes.c @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "arith.h" #include "flags.h" #include "dependency.h" +#include "constructor.h" /* Forward declarations. */ @@ -121,8 +122,13 @@ optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op) else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0 && ! (e->value.function.esym && (e->value.function.esym->attr.elemental - || e->value.function.esym->attr.allocatable)) - && ! (e->value.function.isym && e->value.function.isym->elemental)) + || e->value.function.esym->attr.allocatable + || e->value.function.esym->ts.type != c->expr1->ts.type + || e->value.function.esym->ts.kind != c->expr1->ts.kind)) + && ! (e->value.function.isym + && (e->value.function.isym->elemental + || e->ts.type != c->expr1->ts.type + || e->ts.kind != c->expr1->ts.kind))) { gfc_code *n; @@ -319,6 +325,9 @@ gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data) { int walk_subtrees = 1; gfc_actual_arglist *a; + gfc_ref *r; + gfc_constructor *c; + int result = exprfn (e, &walk_subtrees, data); if (result) return result; @@ -339,6 +348,61 @@ gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data) for (a = (*e)->value.compcall.actual; a; a = a->next) WALK_SUBEXPR (a->expr); break; + + case EXPR_STRUCTURE: + case EXPR_ARRAY: + for (c = gfc_constructor_first ((*e)->value.constructor); c; + c = gfc_constructor_next (c)) + { + WALK_SUBEXPR (c->expr); + if (c->iterator != NULL) + { + WALK_SUBEXPR (c->iterator->var); + WALK_SUBEXPR (c->iterator->start); + WALK_SUBEXPR (c->iterator->end); + WALK_SUBEXPR (c->iterator->step); + } + } + + if ((*e)->expr_type != EXPR_ARRAY) + break; + + /* Fall through to the variable case in order to walk the + the reference. */ + + case EXPR_SUBSTRING: + case EXPR_VARIABLE: + for (r = (*e)->ref; r; r = r->next) + { + gfc_array_ref *ar; + int i; + + switch (r->type) + { + case REF_ARRAY: + ar = &r->u.ar; + if (ar->type == AR_SECTION || ar->type == AR_ELEMENT) + { + for (i=0; i< ar->dimen; i++) + { + WALK_SUBEXPR (ar->start[i]); + WALK_SUBEXPR (ar->end[i]); + WALK_SUBEXPR (ar->stride[i]); + } + } + + break; + + case REF_SUBSTRING: + WALK_SUBEXPR (r->u.ss.start); + WALK_SUBEXPR (r->u.ss.end); + break; + + case REF_COMPONENT: + break; + } + } + default: break; } diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 947f1ff766e..5fdd0d7adb4 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -343,6 +343,8 @@ enum gfc_isym_id GFC_ISYM_CHMOD, GFC_ISYM_CMPLX, GFC_ISYM_COMMAND_ARGUMENT_COUNT, + GFC_ISYM_COMPILER_OPTIONS, + GFC_ISYM_COMPILER_VERSION, GFC_ISYM_COMPLEX, GFC_ISYM_CONJG, GFC_ISYM_CONVERSION, @@ -613,6 +615,8 @@ gfc_reverse; #define BBT_HEADER(self) int priority; struct self *left, *right #define NAMED_INTCST(a,b,c,d) a, +#define NAMED_KINDARRAY(a,b,c,d) a, +#define NAMED_FUNCTION(a,b,c,d) a, typedef enum { ISOFORTRANENV_INVALID = -1, @@ -621,6 +625,8 @@ typedef enum } iso_fortran_env_symbol; #undef NAMED_INTCST +#undef NAMED_KINDARRAY +#undef NAMED_FUNCTION #define NAMED_INTCST(a,b,c,d) a, #define NAMED_REALCST(a,b,c) a, @@ -630,6 +636,7 @@ iso_fortran_env_symbol; #define NAMED_CHARCST(a,b,c) a, #define DERIVED_TYPE(a,b,c) a, #define PROCEDURE(a,b) a, +#define NAMED_FUNCTION(a,b,c,d) a, typedef enum { ISOCBINDING_INVALID = -1, @@ -646,6 +653,7 @@ iso_c_binding_symbol; #undef NAMED_CHARCST #undef DERIVED_TYPE #undef PROCEDURE +#undef NAMED_FUNCTION typedef enum { @@ -784,6 +792,9 @@ typedef struct unsigned alloc_comp:1, pointer_comp:1, proc_pointer_comp:1, private_comp:1, zero_comp:1, coarray_comp:1; + /* This is a temporary selector for SELECT TYPE. */ + unsigned select_type_temporary:1; + /* Attributes set by compiler extensions (!GCC$ ATTRIBUTES). */ unsigned ext_attr:EXT_ATTR_NUM; @@ -1641,7 +1652,8 @@ typedef struct gfc_intrinsic_sym gfc_intrinsic_arg *formal; gfc_typespec ts; unsigned elemental:1, inquiry:1, transformational:1, pure:1, - generic:1, specific:1, actual_ok:1, noreturn:1, conversion:1; + generic:1, specific:1, actual_ok:1, noreturn:1, conversion:1, + from_module:1; int standard; @@ -1996,7 +2008,7 @@ typedef struct { gfc_expr *io_unit, *format_expr, *rec, *advance, *iostat, *size, *iomsg, *id, *pos, *asynchronous, *blank, *decimal, *delim, *pad, *round, - *sign, *extra_comma; + *sign, *extra_comma, *dt_io_kind; gfc_symbol *namelist; /* A format_label of `format_asterisk' indicates the "*" format */ @@ -2634,6 +2646,7 @@ bool gfc_is_intrinsic (gfc_symbol*, int, locus); int gfc_intrinsic_actual_ok (const char *, const bool); gfc_intrinsic_sym *gfc_find_function (const char *); gfc_intrinsic_sym *gfc_find_subroutine (const char *); +gfc_intrinsic_sym *gfc_intrinsic_function_by_id (gfc_isym_id); match gfc_intrinsic_func_interface (gfc_expr *, int); match gfc_intrinsic_sub_interface (gfc_code *, int); @@ -2726,6 +2739,7 @@ bool gfc_has_ultimate_allocatable (gfc_expr *); bool gfc_has_ultimate_pointer (gfc_expr *); gfc_expr* gfc_build_intrinsic_call (const char*, locus, unsigned, ...); +gfc_try gfc_check_vardef_context (gfc_expr*, bool, const char*); /* st.c */ diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index 10492f0d916..391b6e7d214 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -158,7 +158,7 @@ Boston, MA 02110-1301, USA@* @cindex Introduction This manual documents the use of @command{gfortran}, -the GNU Fortran compiler. You can find in this manual how to invoke +the GNU Fortran compiler. You can find in this manual how to invoke @command{gfortran}, as well as its features and incompatibilities. @ifset DEVELOPMENT @@ -208,7 +208,7 @@ Part II: Language Reference @c The following duplicates the text on the TexInfo table of contents. @iftex This manual documents the use of @command{gfortran}, the GNU Fortran -compiler. You can find in this manual how to invoke @command{gfortran}, +compiler. You can find in this manual how to invoke @command{gfortran}, as well as its features and incompatibilities. @ifset DEVELOPMENT @@ -243,7 +243,7 @@ or alternative to, the unix @command{f95} command; The GNU Fortran compiler supports the Fortran 77, 90 and 95 standards completely, parts of the Fortran 2003 and Fortran 2008 standards, and -several vendor extensions. The development goal is to provide the +several vendor extensions. The development goal is to provide the following features: @itemize @bullet @@ -364,11 +364,11 @@ Functionally, this is implemented with a driver program (@command{gcc}) which provides the command-line interface for the compiler. It calls the relevant compiler front-end program (e.g., @command{f951} for Fortran) for each file in the source code, and then calls the assembler -and linker as appropriate to produce the compiled output. In a copy of +and linker as appropriate to produce the compiled output. In a copy of GCC which has been compiled with Fortran language support enabled, @command{gcc} will recognize files with @file{.f}, @file{.for}, @file{.ftn}, @file{.f90}, @file{.f95}, @file{.f03} and @file{.f08} extensions as -Fortran source code, and compile it accordingly. A @command{gfortran} +Fortran source code, and compile it accordingly. A @command{gfortran} driver program is also provided, which is identical to @command{gcc} except that it automatically links the Fortran runtime libraries into the compiled program. @@ -378,7 +378,7 @@ Source files with @file{.f}, @file{.for}, @file{.fpp}, @file{.ftn}, @file{.F}, Source files with @file{.f90}, @file{.f95}, @file{.f03}, @file{.f08}, @file{.F90}, @file{.F95}, @file{.F03} and @file{.F08} extensions are treated as free form. The capitalized versions of either form are run -through preprocessing. Source files with the lower case @file{.fpp} +through preprocessing. Source files with the lower case @file{.fpp} extension are also run through preprocessing. This manual specifically documents the Fortran front end, which handles @@ -404,28 +404,28 @@ Fortran compiler. Many Fortran compilers including GNU Fortran allow passing the source code through a C preprocessor (CPP; sometimes also called the Fortran preprocessor, -FPP) to allow for conditional compilation. In the case of GNU Fortran, -this is the GNU C Preprocessor in the traditional mode. On systems with +FPP) to allow for conditional compilation. In the case of GNU Fortran, +this is the GNU C Preprocessor in the traditional mode. On systems with case-preserving file names, the preprocessor is automatically invoked if the -filename extension is @code{.F}, @code{.FOR}, @code{.FTN}, @code{.fpp}, -@code{.FPP}, @code{.F90}, @code{.F95}, @code{.F03} or @code{.F08}. To manually +filename extension is @file{.F}, @file{.FOR}, @file{.FTN}, @file{.fpp}, +@file{.FPP}, @file{.F90}, @file{.F95}, @file{.F03} or @file{.F08}. To manually invoke the preprocessor on any file, use @option{-cpp}, to disable preprocessing on files where the preprocessor is run automatically, use @option{-nocpp}. If a preprocessed file includes another file with the Fortran @code{INCLUDE} -statement, the included file is not preprocessed. To preprocess included +statement, the included file is not preprocessed. To preprocess included files, use the equivalent preprocessor statement @code{#include}. If GNU Fortran invokes the preprocessor, @code{__GFORTRAN__} is defined and @code{__GNUC__}, @code{__GNUC_MINOR__} and @code{__GNUC_PATCHLEVEL__} can be used to determine the version of the -compiler. See @ref{Top,,Overview,cpp,The C Preprocessor} for details. +compiler. See @ref{Top,,Overview,cpp,The C Preprocessor} for details. While CPP is the de-facto standard for preprocessing Fortran code, Part 3 of the Fortran 95 standard (ISO/IEC 1539-3:1998) defines Conditional Compilation, which is not widely used and not directly -supported by the GNU Fortran compiler. You can use the program coco +supported by the GNU Fortran compiler. You can use the program coco to preprocess such files (@uref{http://www.daniellnagle.com/coco.html}). @@ -474,9 +474,8 @@ standard-compliant Fortran 95, Fortran 90, and Fortran 77 programs, including a number of standard and non-standard extensions, and can be used on real-world programs. In particular, the supported extensions include OpenMP, Cray-style pointers, and several Fortran 2003 and Fortran -2008 features such as enumeration, stream I/O, and some of the -enhancements to allocatable array support from TR 15581. However, it is -still under development and has a few remaining rough edges. +2008 features, including TR 15581. However, it is still under +development and has a few remaining rough edges. At present, the GNU Fortran compiler passes the @uref{http://www.fortran-2000.com/ArnaudRecipes/fcvs21_f95.html, @@ -491,7 +490,7 @@ large real-world programs, including @uref{http://mysite.verizon.net/serveall/moene.pdf, the HIRLAM weather-forecasting code} and @uref{http://www.theochem.uwa.edu.au/tonto/, the Tonto quantum -chemistry package}; see @url{http://gcc.gnu.org/wiki/GfortranApps} for an +chemistry package}; see @url{http://gcc.gnu.org/@/wiki/@/GfortranApps} for an extended list. Among other things, the GNU Fortran compiler is intended as a replacement @@ -521,25 +520,17 @@ future standards---in particular, Fortran 2003 and Fortran 2008. The GNU Fortran compiler implements ISO/IEC 1539:1997 (Fortran 95). As such, it can also compile essentially all standard-compliant Fortran 90 and Fortran 77 programs. It also supports -the ISO/IEC TR-15581 enhancements to allocatable arrays, and -the @uref{http://www.openmp.org/drupal/mp-documents/spec25.pdf, -OpenMP Application Program Interface v2.5} specification. +the ISO/IEC TR-15581 enhancements to allocatable arrays. In the future, the GNU Fortran compiler will also support ISO/IEC -1539-1:2004 (Fortran 2003) and future Fortran standards. Partial support -of that standard is already provided; the current status of Fortran 2003 -support is reported in the @ref{Fortran 2003 status} section of the -documentation. - -The next version of the Fortran standard (Fortran 2008) is currently -being developed and the GNU Fortran compiler supports some of its new -features. This support is based on the latest draft of the standard -(available from @url{http://www.nag.co.uk/sc22wg5/}) and no guarantee of -future compatibility is made, as the final standard might differ from the -draft. For more information, see the @ref{Fortran 2008 status} section. +1539-1:2004 (Fortran 2003), ISO/IEC 1539-1:2010 (Fortran 2008) and +future Fortran standards. Partial support of the Fortran 2003 and +Fortran 2008 standard is already provided; the current status of the +support is reported in the @ref{Fortran 2003 status} and +@ref{Fortran 2008 status} sections of the documentation. Additionally, the GNU Fortran compilers supports the OpenMP specification -(version 3.0, @url{http://openmp.org/wp/openmp-specifications/}). +(version 3.0, @url{http://openmp.org/@/wp/@/openmp-specifications/}). @node Varying Length Character Strings @subsection Varying Length Character Strings @@ -548,9 +539,9 @@ Additionally, the GNU Fortran compilers supports the OpenMP specification @cindex strings, varying length The Fortran 95 standard specifies in Part 2 (ISO/IEC 1539-2:2000) -varying length character strings. While GNU Fortran currently does not +varying length character strings. While GNU Fortran currently does not support such strings directly, there exist two Fortran implementations -for them, which work with GNU Fortran. They can be found at +for them, which work with GNU Fortran. They can be found at @uref{http://www.fortran.com/@/iso_varying_string.f95} and at @uref{ftp://ftp.nag.co.uk/@/sc22wg5/@/ISO_VARYING_STRING/}. @@ -627,7 +618,7 @@ The default value is 0. This environment variable controls where library output is sent. If the first letter is @samp{y}, @samp{Y} or @samp{1}, standard -error is used. If the first letter is @samp{n}, @samp{N} or +error is used. If the first letter is @samp{n}, @samp{N} or @samp{0}, standard output is used. @node GFORTRAN_TMPDIR @@ -643,7 +634,7 @@ If these are missing, the default is @file{/tmp}. This environment variable controls whether all I/O is unbuffered. If the first letter is @samp{y}, @samp{Y} or @samp{1}, all I/O is -unbuffered. This will slow down small sequential reads and writes. If +unbuffered. This will slow down small sequential reads and writes. If the first letter is @samp{n}, @samp{N} or @samp{0}, I/O is buffered. This is the default. @@ -652,7 +643,7 @@ This is the default. The environment variable named @env{GFORTRAN_UNBUFFERED_PRECONNECTED} controls whether I/O on a preconnected unit (i.e.@: STDOUT or STDERR) is unbuffered. If -the first letter is @samp{y}, @samp{Y} or @samp{1}, I/O is unbuffered. This +the first letter is @samp{y}, @samp{Y} or @samp{1}, I/O is unbuffered. This will slow down small sequential reads and writes. If the first letter is @samp{n}, @samp{N} or @samp{0}, I/O is buffered. This is the default. @@ -662,7 +653,7 @@ is @samp{n}, @samp{N} or @samp{0}, I/O is buffered. This is the default. If the first letter is @samp{y}, @samp{Y} or @samp{1}, filename and line numbers for runtime errors are printed. If the first letter is @samp{n}, @samp{N} or @samp{0}, don't print filename and line numbers -for runtime errors. The default is to print the location. +for runtime errors. The default is to print the location. @node GFORTRAN_OPTIONAL_PLUS @section @env{GFORTRAN_OPTIONAL_PLUS}---Print leading + where permitted @@ -671,7 +662,7 @@ If the first letter is @samp{y}, @samp{Y} or @samp{1}, a plus sign is printed where permitted by the Fortran standard. If the first letter is @samp{n}, @samp{N} or @samp{0}, a plus sign is not printed -in most cases. Default is not to print plus signs. +in most cases. Default is not to print plus signs. @node GFORTRAN_DEFAULT_RECL @section @env{GFORTRAN_DEFAULT_RECL}---Default record length for new files @@ -768,8 +759,8 @@ users who do not have the source code of their program available. If the @env{GFORTRAN_ERROR_DUMPCORE} variable is set to @samp{y}, @samp{Y} or @samp{1} (only the first letter is relevant) -then library run-time errors cause core dumps. To disable the core -dumps, set the variable to @samp{n}, @samp{N}, @samp{0}. Default +then library run-time errors cause core dumps. To disable the core +dumps, set the variable to @samp{n}, @samp{N}, @samp{0}. Default is not to core dump unless the @option{-fdump-core} compile option was used. @@ -780,7 +771,7 @@ If the @env{GFORTRAN_ERROR_BACKTRACE} variable is set to @samp{y}, @samp{Y} or @samp{1} (only the first letter is relevant) then a backtrace is printed when a run-time error occurs. To disable the backtracing, set the variable to -@samp{n}, @samp{N}, @samp{0}. Default is not to print a backtrace +@samp{n}, @samp{N}, @samp{0}. Default is not to print a backtrace unless the @option{-fbacktrace} compile option was used. @@ -820,7 +811,7 @@ Intrinsics @code{command_argument_count}, @code{get_command}, @item @cindex array, constructors @cindex @code{[...]} -Array constructors using square brackets. That is, @code{[...]} rather +Array constructors using square brackets. That is, @code{[...]} rather than @code{(/.../)}. Type-specification for array constructors like @code{(/ some-type :: ... /)}. @@ -938,21 +929,103 @@ Extension of derived-types (the @code{EXTENDS(...)} syntax). @node Fortran 2008 status @section Fortran 2008 status -The next version of the Fortran standard after Fortran 2003 is currently -being worked on by the Working Group 5 of Sub-Committee 22 of the Joint -Technical Committee 1 of the International Organization for -Standardization (ISO) and the International Electrotechnical Commission -(IEC). This group is known as @uref{http://www.nag.co.uk/sc22wg5/, WG5}. -The next revision of the Fortran standard is informally referred to as -Fortran 2008, reflecting its planned release year. The GNU Fortran -compiler has support for some of the new features in Fortran 2008. This -support is based on the latest draft, available from -@url{http://www.nag.co.uk/sc22wg5/}. However, as the final standard may -differ from the drafts, no guarantee of backward compatibility can be -made and you should only use it for experimental purposes. +The latest version of the Fortran standard is ISO/IEC 1539-1:2010, informally +known as Fortran 2008. The official version is available from International +Organization for Standardization (ISO) or its national member organizations. +The the final draft (FDIS) can be downloaded free of charge from +@url{http://www.nag.co.uk/@/sc22wg5/@/links.html}. Fortran is developed by the +Working Group 5 of Sub-Committee 22 of the Joint Technical Committee 1 of the +International Organization for Standardization and the International +Electrotechnical Commission (IEC). This group is known as +@uref{http://www.nag.co.uk/sc22wg5/, WG5}. + +The GNU Fortran supports several of the new features of Fortran 2008; the +@uref{http://gcc.gnu.org/wiki/Fortran2008Status, wiki} has some information +about the current Fortran 2008 implementation status. In particular, the +following is implemented. + +@itemize +@item The @option{-std=f2008} option and support for the file extensions +@file{.f08} and @file{.F08}. + +@item The @code{OPEN} statement now supports the @code{NEWUNIT=} option, +which returns a unique file unit, thus preventing inadvertent use of the +same unit in different parts of the program. + +@item The @code{g0} format descriptor and unlimited format items. + +@item The mathematical intrinsics @code{ASINH}, @code{ACOSH}, @code{ATANH}, +@code{ERF}, @code{ERFC}, @code{GAMMA}, @code{LOG_GAMMA}, @code{BESSEL_J0}, +@code{BESSEL_J1}, @code{BESSEL_JN}, @code{BESSEL_Y0}, @code{BESSEL_Y1}, +@code{BESSEL_YN}, @code{HYPOT}, @code{NORM2}, and @code{ERFC_SCALED}. + +@item Using complex arguments with @code{TAN}, @code{SINH}, @code{COSH}, +@code{TANH}, @code{ASIN}, @code{ACOS}, and @code{ATAN} is now possible; +@code{ATAN}(@var{Y},@var{X}) is now an alias for @code{ATAN2}(@var{Y},@var{X}). + +@item Support of the @code{PARITY} intrinsic functions. + +@item The following bit intrinsics: @code{LEADZ} and @code{TRAILZ} for +counting the number of leading and trailing zero bits, @code{POPCNT} and +@code{POPPAR} for counting the number of one bits and returning the parity; +@code{BGE}, @code{BGT}, @code{BLE}, and @code{BLT} for bitwise comparisons; +@code{DSHIFTL} and @code{DSHIFTR} for combined left and right shifts, +@code{MASKL} and @code{MASKR} for simple left and right justified masks, +@code{MERGE_BITS} for a bitwise merge using a mask, @code{SHIFTA}, +@code{SHIFTL} and @code{SHIFTR} for shift operations, and the +transformational bit intrinsics @code{IALL}, @code{IANY} and @code{IPARITY}. + +@item Support of the @code{EXECUTE_COMMAND_LINE} intrinsic subroutine. + +@item Support for the @code{STORAGE_SIZE} intrinsic inquiry function. + +@item The @code{INT@{8,16,32@}} and @code{REAL@{32,64,128@}} kind type +parameters of the intrinsic module @code{ISO_FORTRAN_ENV}. + +@item Experimental coarray support (for one image only), use the +@option{-fcoarray=single} flag to enable it. + +@item The @code{BLOCK} construct is supported. + +@item The @code{STOP} and the new @code{ERROR STOP} statements now +support all constant expressions. + +@item Support for the @code{CONTIGUOUS} attribute. + +@item Support for @code{ALLOCATE} with @code{MOLD}. + +@item Support for the @code{IMPURE} attribute for procedures, which +allows for @code{ELEMENTAL} procedures without the restrictions of +@code{PURE}. + +@item Null pointers (including @code{NULL()}) and not-allocated variables +can be used as actual argument to optional non-pointer, non-allocatable +dummy arguments, denoting an absent argument. + +@item Non-pointer variables with @code{TARGET} attribute can be used as +actual argument to @code{POINTER} dummies with @code{INTENT(IN)}. + +@item Pointers including procedure pointers and those in a derived +type (pointer components) can now be initialized by a target instead +of only by @code{NULL}. + +@item The @code{EXIT} statement (with construct-name) can be now be +used to leave not only the @code{DO} but also the @code{ASSOCIATE}, +@code{BLOCK}, @code{IF}, @code{SELECT CASE} and @code{SELECT TYPE} +constructs. + +@item Internal procedures can now be used as actual argument. + +@item Minor features: obsolesce diagnostics for @code{ENTRY} with +@option{-std=f2008}; a line may start with a semicolon; for internal +and module procedures @code{END} can be used instead of +@code{END SUBROUTINE} and @code{END FUNCTION}; @code{SELECTED_REAL_KIND} +now also takes a @code{RADIX} argument; intrinsic types are supported +for @code{TYPE}(@var{intrinsic-type-spec}); multiple type-bound procedures +can be declared in a single @code{PROCEDURE} statement; implied-shape +arrays are supported for named constants (@code{PARAMETER}). +@end itemize -The @uref{http://gcc.gnu.org/wiki/Fortran2008Status, wiki} has some information -about the current Fortran 2008 implementation status. @c --------------------------------------------------------------------- @@ -1025,7 +1098,7 @@ as follows. A @code{LOGICAL(KIND=N)} variable is represented as an @code{INTEGER(KIND=N)} variable, however, with only two permissible values: @code{1} for @code{.TRUE.} and @code{0} for -@code{.FALSE.}. Any other integer value results in undefined behavior. +@code{.FALSE.}. Any other integer value results in undefined behavior. Note that for mixed-language programming using the @code{ISO_C_BINDING} feature, there is a @code{C_BOOL} kind that can @@ -1067,7 +1140,7 @@ extensions. @cindex extensions, implemented GNU Fortran implements a number of extensions over standard -Fortran. This chapter contains information on their syntax and +Fortran. This chapter contains information on their syntax and meaning. There are currently two categories of GNU Fortran extensions, those that provide functionality beyond that provided by any standard, and those that are supported by GNU Fortran @@ -1101,7 +1174,7 @@ without warning. @subsection Old-style kind specifications @cindex kind, old-style -GNU Fortran allows old-style kind specifications in declarations. These +GNU Fortran allows old-style kind specifications in declarations. These look like: @smallexample TYPESPEC*size x,y,z @@ -1182,7 +1255,7 @@ $END It should be noted that the default terminator is @samp{/} rather than @samp{&END}. -Querying of the namelist when inputting from stdin. After at least +Querying of the namelist when inputting from stdin. After at least one space, entering @samp{?} sends to stdout the namelist name and the names of the variables in the namelist: @smallexample @@ -1282,15 +1355,15 @@ of the @code{READ} statement, and the output item lists of the @cindex BOZ literal constants Besides decimal constants, Fortran also supports binary (@code{b}), -octal (@code{o}) and hexadecimal (@code{z}) integer constants. The +octal (@code{o}) and hexadecimal (@code{z}) integer constants. The syntax is: @samp{prefix quote digits quote}, were the prefix is either @code{b}, @code{o} or @code{z}, quote is either @code{'} or @code{"} and the digits are for binary @code{0} or @code{1}, for octal between @code{0} and @code{7}, and for hexadecimal between -@code{0} and @code{F}. (Example: @code{b'01011101'}.) +@code{0} and @code{F}. (Example: @code{b'01011101'}.) Up to Fortran 95, BOZ literals were only allowed to initialize -integer variables in DATA statements. Since Fortran 2003 BOZ literals +integer variables in DATA statements. Since Fortran 2003 BOZ literals are also allowed as argument of @code{REAL}, @code{DBLE}, @code{INT} and @code{CMPLX}; the result is the same as if the integer BOZ literal had been converted by @code{TRANSFER} to, respectively, @@ -1300,7 +1373,7 @@ As GNU Fortran extension the intrinsic procedures @code{FLOAT}, As an extension, GNU Fortran allows hexadecimal BOZ literal constants to be specified using the @code{X} prefix, in addition to the standard -@code{Z} prefix. The BOZ literal can also be specified by adding a +@code{Z} prefix. The BOZ literal can also be specified by adding a suffix to the string, for example, @code{Z'ABC'} and @code{'ABC'Z} are equivalent. @@ -1310,7 +1383,7 @@ In DATA statements, in direct assignments, where the right-hand side only contains a BOZ literal constant, and for old-style initializers of the form @code{integer i /o'0173'/}, the constant is transferred as if @code{TRANSFER} had been used; for @code{COMPLEX} numbers, only -the real part is initialized unless @code{CMPLX} is used. In all other +the real part is initialized unless @code{CMPLX} is used. In all other cases, the BOZ literal constant is converted to an @code{INTEGER} value with the largest decimal representation. This value is then converted numerically to the type and kind of the variable in question. @@ -1494,10 +1567,10 @@ example: ipt = loc(target) @end smallexample As long as @code{ipt} remains unchanged, @code{iarr} is now an alias for -@code{target}. The optimizer, however, will not detect this aliasing, so +@code{target}. The optimizer, however, will not detect this aliasing, so it is unsafe to use @code{iarr} and @code{target} simultaneously. Using a pointee in any way that violates the Fortran aliasing rules or -assumptions is illegal. It is the user's responsibility to avoid doing +assumptions is illegal. It is the user's responsibility to avoid doing this; the compiler works under the assumption that no such aliasing occurs. @@ -1513,10 +1586,10 @@ will ``incorrectly'' optimize code with illegal aliasing.) There are a number of restrictions on the attributes that can be applied to Cray pointers and pointees. Pointees may not have the @code{ALLOCATABLE}, @code{INTENT}, @code{OPTIONAL}, @code{DUMMY}, -@code{TARGET}, @code{INTRINSIC}, or @code{POINTER} attributes. Pointers +@code{TARGET}, @code{INTRINSIC}, or @code{POINTER} attributes. Pointers may not have the @code{DIMENSION}, @code{POINTER}, @code{TARGET}, @code{ALLOCATABLE}, @code{EXTERNAL}, or @code{INTRINSIC} attributes, nor -may they be function results. Pointees may not occur in more than one +may they be function results. Pointees may not occur in more than one pointer statement. A pointee cannot be a pointer. Pointees cannot occur in equivalence, common, or data statements. @@ -1610,7 +1683,7 @@ free-form source code; the @code{c$omp}, @code{*$omp} and @code{!$omp} directives in fixed form; the @code{!$} conditional compilation sentinels in free form; and the @code{c$}, @code{*$} and @code{!$} sentinels in fixed form, @command{gfortran} needs to be invoked with the -@option{-fopenmp}. This also arranges for automatic linking of the +@option{-fopenmp}. This also arranges for automatic linking of the GNU OpenMP runtime library @ref{Top,,libgomp,libgomp,GNU OpenMP runtime library}. @@ -1636,16 +1709,16 @@ Please note: @itemize @item @option{-fopenmp} implies @option{-frecursive}, i.e., all local arrays -will be allocated on the stack. When porting existing code to OpenMP, +will be allocated on the stack. When porting existing code to OpenMP, this may lead to surprising results, especially to segmentation faults if the stacksize is limited. @item On glibc-based systems, OpenMP enabled applications cannot be statically -linked due to limitations of the underlying pthreads-implementation. It +linked due to limitations of the underlying pthreads-implementation. It might be possible to get a working solution if @command{-Wl,--whole-archive -lpthread -Wl,--no-whole-archive} is added -to the command line. However, this is not supported by @command{gcc} and +to the command line. However, this is not supported by @command{gcc} and thus not recommended. @end itemize @@ -1660,9 +1733,9 @@ GNU Fortran supports argument list functions @code{%VAL}, @code{%REF} and @code{%LOC} statements, for backward compatibility with g77. It is recommended that these should be used only for code that is accessing facilities outside of GNU Fortran, such as operating system -or windowing facilities. It is best to constrain such uses to isolated +or windowing facilities. It is best to constrain such uses to isolated portions of a program--portions that deal specifically and exclusively -with low-level, system-dependent facilities. Such portions might well +with low-level, system-dependent facilities. Such portions might well provide a portable interface for use by the program as a whole, but are themselves not portable, and should be thoroughly tested each time they are rebuilt using a new compiler or version of a compiler. @@ -1685,7 +1758,7 @@ C @end smallexample For details refer to the g77 manual -@uref{http://gcc.gnu.org/onlinedocs/gcc-3.4.6/g77/index.html#Top}. +@uref{http://gcc.gnu.org/@/onlinedocs/@/gcc-3.4.6/@/g77/@/index.html#Top}. Also, @code{c_by_val.f} and its partner @code{c_by_val.c} of the GNU Fortran testsuite are worth a look. @@ -1731,7 +1804,7 @@ code that uses them running with the GNU Fortran compiler. Structures are user-defined aggregate data types; this functionality was standardized in Fortran 90 with an different syntax, under the name of -``derived types''. Here is an example of code using the non portable +``derived types''. Here is an example of code using the non portable structure syntax: @example @@ -1809,7 +1882,7 @@ GNU Fortran doesn't support the @code{ENCODE} and @code{DECODE} statements. These statements are best replaced by @code{READ} and @code{WRITE} statements involving internal files (@code{CHARACTER} variables and arrays), which have been part of the Fortran standard since -Fortran 77. For example, replace a code fragment like +Fortran 77. For example, replace a code fragment like @smallexample INTEGER*1 LINE(80) @@ -1857,10 +1930,10 @@ c ... Code that sets A, B and C @cindex @code{FORMAT} A variable @code{FORMAT} expression is format statement which includes -angle brackets enclosing a Fortran expression: @code{FORMAT(I<N>)}. GNU -Fortran does not support this legacy extension. The effect of variable +angle brackets enclosing a Fortran expression: @code{FORMAT(I<N>)}. GNU +Fortran does not support this legacy extension. The effect of variable format expressions can be reproduced by using the more powerful (and -standard) combination of internal output and string formats. For example, +standard) combination of internal output and string formats. For example, replace a code fragment like this: @smallexample @@ -1901,8 +1974,8 @@ c Some Fortran compilers, including @command{g77}, let the user declare complex functions with the syntax @code{COMPLEX FUNCTION name*16()}, as -well as @code{COMPLEX*16 FUNCTION name()}. Both are non-standard, legacy -extensions. @command{gfortran} accepts the latter form, which is more +well as @code{COMPLEX*16 FUNCTION name()}. Both are non-standard, legacy +extensions. @command{gfortran} accepts the latter form, which is more common, but not the former. @@ -1923,7 +1996,7 @@ common, but not the former. @end menu This chapter is about mixed-language interoperability, but also applies -if one links Fortran code compiled by different compilers. In most cases, +if one links Fortran code compiled by different compilers. In most cases, use of the C Binding features of the Fortran 2003 standard is sufficient, and their use is highly recommended. @@ -1943,18 +2016,18 @@ and their use is highly recommended. Since Fortran 2003 (ISO/IEC 1539-1:2004(E)) there is a standardized way to generate procedure and derived-type declarations and global variables which are interoperable with C -(ISO/IEC 9899:1999). The @code{bind(C)} attribute has been added +(ISO/IEC 9899:1999). The @code{bind(C)} attribute has been added to inform the compiler that a symbol shall be interoperable with C; -also, some constraints are added. Note, however, that not -all C features have a Fortran equivalent or vice versa. For instance, +also, some constraints are added. Note, however, that not +all C features have a Fortran equivalent or vice versa. For instance, neither C's unsigned integers nor C's functions with variable number of arguments have an equivalent in Fortran. Note that array dimensions are reversely ordered in C and that arrays in C always start with index 0 while in Fortran they start by default with -1. Thus, an array declaration @code{A(n,m)} in Fortran matches +1. Thus, an array declaration @code{A(n,m)} in Fortran matches @code{A[m][n]} in C and accessing the element @code{A(i,j)} matches -@code{A[j-1][i-1]}. The element following @code{A(i,j)} (C: @code{A[j-1][i-1]}; +@code{A[j-1][i-1]}. The element following @code{A(i,j)} (C: @code{A[j-1][i-1]}; assuming @math{i < n}) in memory is @code{A(i+1,j)} (C: @code{A[j-1][i]}). @node Intrinsic Types @@ -1962,15 +2035,15 @@ assuming @math{i < n}) in memory is @code{A(i+1,j)} (C: @code{A[j-1][i]}). In order to ensure that exactly the same variable type and kind is used in C and Fortran, the named constants shall be used which are defined in the -@code{ISO_C_BINDING} intrinsic module. That module contains named constants +@code{ISO_C_BINDING} intrinsic module. That module contains named constants for kind parameters and character named constants for the escape sequences -in C. For a list of the constants, see @ref{ISO_C_BINDING}. +in C. For a list of the constants, see @ref{ISO_C_BINDING}. @node Derived Types and struct @subsection Derived Types and struct For compatibility of derived types with @code{struct}, one needs to use -the @code{BIND(C)} attribute in the type declaration. For instance, the +the @code{BIND(C)} attribute in the type declaration. For instance, the following type declaration @smallexample @@ -1999,8 +2072,8 @@ matches the following @code{struct} declaration in C Derived types with the C binding attribute shall not have the @code{sequence} attribute, type parameters, the @code{extends} attribute, nor type-bound -procedures. Every component must be of interoperable type and kind and may not -have the @code{pointer} or @code{allocatable} attribute. The names of the +procedures. Every component must be of interoperable type and kind and may not +have the @code{pointer} or @code{allocatable} attribute. The names of the variables are irrelevant for interoperability. As there exist no direct Fortran equivalents, neither unions nor structs @@ -2010,7 +2083,7 @@ with bit field or variable-length array members are interoperable. @subsection Interoperable Global Variables Variables can be made accessible from C using the C binding attribute, -optionally together with specifying a binding name. Those variables +optionally together with specifying a binding name. Those variables have to be declared in the declaration part of a @code{MODULE}, be of interoperable type, and have neither the @code{pointer} nor the @code{allocatable} attribute. @@ -2026,22 +2099,22 @@ the @code{allocatable} attribute. Here, @code{_MyProject_flags} is the case-sensitive name of the variable as seen from C programs while @code{global_flag} is the case-insensitive -name as seen from Fortran. If no binding name is specified, as for +name as seen from Fortran. If no binding name is specified, as for @var{tp}, the C binding name is the (lowercase) Fortran binding name. If a binding name is specified, only a single variable may be after the -double colon. Note of warning: You cannot use a global variable to +double colon. Note of warning: You cannot use a global variable to access @var{errno} of the C library as the C standard allows it to be -a macro. Use the @code{IERRNO} intrinsic (GNU extension) instead. +a macro. Use the @code{IERRNO} intrinsic (GNU extension) instead. @node Interoperable Subroutines and Functions @subsection Interoperable Subroutines and Functions Subroutines and functions have to have the @code{BIND(C)} attribute to -be compatible with C. The dummy argument declaration is relatively -straightforward. However, one needs to be careful because C uses +be compatible with C. The dummy argument declaration is relatively +straightforward. However, one needs to be careful because C uses call-by-value by default while Fortran behaves usually similar to -call-by-reference. Furthermore, strings and pointers are handled -differently. Note that only explicit size and assumed-size arrays are +call-by-reference. Furthermore, strings and pointers are handled +differently. Note that only explicit size and assumed-size arrays are supported but not assumed-shape or allocatable arrays. To pass a variable by value, use the @code{VALUE} attribute. @@ -2063,10 +2136,10 @@ matches the Fortran declaration Note that pointer arguments also frequently need the @code{VALUE} attribute, see @ref{Working with Pointers}. -Strings are handled quite differently in C and Fortran. In C a string +Strings are handled quite differently in C and Fortran. In C a string is a @code{NUL}-terminated array of characters while in Fortran each string has a length associated with it and is thus not terminated (by e.g. -@code{NUL}). For example, if one wants to use the following C function, +@code{NUL}). For example, if one wants to use the following C function, @smallexample #include <stdio.h> @@ -2090,13 +2163,13 @@ to print ``Hello World'' from Fortran, one can call it using @end smallexample As the example shows, one needs to ensure that the -string is @code{NUL} terminated. Additionally, the dummy argument +string is @code{NUL} terminated. Additionally, the dummy argument @var{string} of @code{print_C} is a length-one assumed-size -array; using @code{character(len=*)} is not allowed. The example +array; using @code{character(len=*)} is not allowed. The example above uses @code{c_char_"Hello World"} to ensure the string literal has the right type; typically the default character kind and @code{c_char} are the same and thus @code{"Hello World"} -is equivalent. However, the standard does not guarantee this. +is equivalent. However, the standard does not guarantee this. The use of strings is now further illustrated using the C library function @code{strncpy}, whose prototype is @@ -2106,7 +2179,7 @@ function @code{strncpy}, whose prototype is @end smallexample The function @code{strncpy} copies at most @var{n} characters from -string @var{s2} to @var{s1} and returns @var{s1}. In the following +string @var{s2} to @var{s1} and returns @var{s1}. In the following example, we ignore the return value: @smallexample @@ -2136,7 +2209,7 @@ The intrinsic procedures are described in @ref{Intrinsic Procedures}. @subsection Working with Pointers C pointers are represented in Fortran via the special opaque derived type -@code{type(c_ptr)} (with private components). Thus one needs to +@code{type(c_ptr)} (with private components). Thus one needs to use intrinsic conversion procedures to convert from or to C pointers. For example, @@ -2284,16 +2357,16 @@ END MODULE m @subsection Further Interoperability of Fortran with C Assumed-shape and allocatable arrays are passed using an array descriptor -(dope vector). The internal structure of the array descriptor used -by GNU Fortran is not yet documented and will change. There will also be +(dope vector). The internal structure of the array descriptor used +by GNU Fortran is not yet documented and will change. There will also be a Technical Report (TR 29113) which standardizes an interoperable -array descriptor. Until then, you can use the Chasm Language +array descriptor. Until then, you can use the Chasm Language Interoperability Tools, @url{http://chasm-interop.sourceforge.net/}, which provide an interface to GNU Fortran's array descriptor. The technical report 29113 will presumably also include support for C-interoperable @code{OPTIONAL} and for assumed-rank and assumed-type -dummy arguments. However, the TR has neither been approved nor implemented +dummy arguments. However, the TR has neither been approved nor implemented in GNU Fortran; therefore, these features are not yet available. @@ -2302,10 +2375,10 @@ in GNU Fortran; therefore, these features are not yet available. @section GNU Fortran Compiler Directives The Fortran standard standard describes how a conforming program shall -behave; however, the exact implementation is not standardized. In order +behave; however, the exact implementation is not standardized. In order to allow the user to choose specific implementation details, compiler directives can be used to set attributes of variables and procedures -which are not part of the standard. Whether a given attribute is +which are not part of the standard. Whether a given attribute is supported and its exact effects depend on both the operating system and on the processor; see @ref{Top,,C Extensions,gcc,Using the GNU Compiler Collection (GCC)} @@ -2323,13 +2396,13 @@ instead using the stack Besides changing the calling convention, the attributes also influence the decoration of the symbol name, e.g., by a leading underscore or by -a trailing at-sign followed by the number of bytes on the stack. When +a trailing at-sign followed by the number of bytes on the stack. When assigning a procedure to a procedure pointer, both should use the same calling convention. On some systems, procedures and global variables (module variables and @code{COMMON} blocks) need special handling to be accessible when they -are in a shared library. The following attributes are available: +are in a shared library. The following attributes are available: @itemize @item @code{DLLEXPORT} -- provide a global pointer to a pointer in the DLL @@ -2364,14 +2437,14 @@ the same declaration part as the variable or procedure pointer. Even if you are doing mixed-language programming, it is very likely that you do not need to know or use the information in this -section. Since it is about the internal structure of GNU Fortran, +section. Since it is about the internal structure of GNU Fortran, it may also change in GCC minor releases. When you compile a @code{PROGRAM} with GNU Fortran, a function with the name @code{main} (in the symbol table of the object file) is generated, which initializes the libgfortran library and then calls the actual program which uses the name @code{MAIN__}, for -historic reasons. If you link GNU Fortran compiled procedures +historic reasons. If you link GNU Fortran compiled procedures to, e.g., a C or C++ program or to a Fortran program compiled by a different compiler, the libgfortran library is not initialized and thus a few intrinsic procedures do not work properly, e.g. @@ -2380,16 +2453,16 @@ those for obtaining the command-line arguments. Therefore, if your @code{PROGRAM} is not compiled with GNU Fortran and the GNU Fortran compiled procedures require intrinsics relying on the library initialization, you need to -initialize the library yourself. Using the default options, +initialize the library yourself. Using the default options, gfortran calls @code{_gfortran_set_args} and -@code{_gfortran_set_options}. The initialization of the former +@code{_gfortran_set_options}. The initialization of the former is needed if the called procedures access the command line (and for backtracing); the latter sets some flags based on the -standard chosen or to enable backtracing. In typical programs, +standard chosen or to enable backtracing. In typical programs, it is not necessary to call any initialization function. If your @code{PROGRAM} is compiled with GNU Fortran, you shall -not call any of the following functions. The libgfortran +not call any of the following functions. The libgfortran initialization functions are shown in C syntax but using C bindings they are also accessible from Fortran. @@ -2403,7 +2476,7 @@ bindings they are also accessible from Fortran. @item @emph{Description}: @code{_gfortran_set_args} saves the command-line arguments; this initialization is required if any of the command-line intrinsics -is called. Additionally, it shall be called if backtracing is +is called. Additionally, it shall be called if backtracing is enabled (see @code{_gfortran_set_options}). @item @emph{Syntax}: @@ -2437,10 +2510,10 @@ int main (int argc, char *argv[]) @item @emph{Description}: @code{_gfortran_set_options} sets several flags related to the Fortran standard to be used, whether backtracing or core dumps should be enabled -and whether range checks should be performed. The syntax allows for +and whether range checks should be performed. The syntax allows for upward compatibility since the number of passed flags is specified; for -non-passed flags, the default value is used. See also -@pxref{Code Gen Options}. Please note that not all flags are actually +non-passed flags, the default value is used. See also +@pxref{Code Gen Options}. Please note that not all flags are actually used. @item @emph{Syntax}: @@ -2464,23 +2537,23 @@ Possible values are (bitwise or-ed) @code{GFC_STD_F77} (1), | GFC_STD_F95_DEL | GFC_STD_F95 | GFC_STD_F2003 | GFC_STD_F2008 | GFC_STD_F2008_OBS | GFC_STD_F77 | GFC_STD_GNU | GFC_STD_LEGACY}. @item @var{option}[1] @tab Standard-warning flag; prints a warning to -standard error. Default: @code{GFC_STD_F95_DEL | GFC_STD_LEGACY}. +standard error. Default: @code{GFC_STD_F95_DEL | GFC_STD_LEGACY}. @item @var{option}[2] @tab If non zero, enable pedantic checking. Default: off. @item @var{option}[3] @tab If non zero, enable core dumps on run-time -errors. Default: off. +errors. Default: off. @item @var{option}[4] @tab If non zero, enable backtracing on run-time -errors. Default: off. +errors. Default: off. Note: Installs a signal handler and requires command-line initialization using @code{_gfortran_set_args}. @item @var{option}[5] @tab If non zero, supports signed zeros. Default: enabled. -@item @var{option}[6] @tab Enables run-time checking. Possible values +@item @var{option}[6] @tab Enables run-time checking. Possible values are (bitwise or-ed): GFC_RTCHECK_BOUNDS (1), GFC_RTCHECK_ARRAY_TEMPS (2), GFC_RTCHECK_RECURSION (4), GFC_RTCHECK_DO (16), GFC_RTCHECK_POINTER (32). Default: disabled. @item @var{option}[7] @tab If non zero, range checking is enabled. -Default: enabled. See -frange-check (@pxref{Code Gen Options}). +Default: enabled. See -frange-check (@pxref{Code Gen Options}). @end multitable @item @emph{Example}: @@ -2541,7 +2614,7 @@ for unformatted files. @item @emph{Arguments}: @multitable @columnfractions .15 .70 @item @var{val} @tab Length of the record marker; valid values -are 4 and 8. Default is 4. +are 4 and 8. Default is 4. @end multitable @item @emph{Example}: @@ -2565,7 +2638,7 @@ int main (int argc, char *argv[]) @table @asis @item @emph{Description}: @code{_gfortran_set_fpe} sets the IEEE exceptions for which a -Floating Point Exception (FPE) should be raised. On most systems, +Floating Point Exception (FPE) should be raised. On most systems, this will result in a SIGFPE signal being sent and the program being interrupted. @@ -2574,7 +2647,7 @@ being interrupted. @item @emph{Arguments}: @multitable @columnfractions .15 .70 -@item @var{option}[0] @tab IEEE exceptions. Possible values are +@item @var{option}[0] @tab IEEE exceptions. Possible values are (bitwise or-ed) zero (0, default) no trapping, @code{GFC_FPE_INVALID} (1), @code{GFC_FPE_DENORMAL} (2), @code{GFC_FPE_ZERO} (4), @code{GFC_FPE_OVERFLOW} (8), @@ -2603,7 +2676,7 @@ int main (int argc, char *argv[]) @table @asis @item @emph{Description}: @code{_gfortran_set_max_subrecord_length} set the maximum length -for a subrecord. This option only makes sense for testing and +for a subrecord. This option only makes sense for testing and debugging of unformatted I/O. @item @emph{Syntax}: @@ -2755,8 +2828,8 @@ keep code private on request. @item Bug hunting/squishing Find bugs and write more test cases! Test cases are especially very welcome, because it allows us to concentrate on fixing bugs instead of -isolating them. Going through the bugzilla database at -@url{http://gcc.gnu.org/bugzilla/} to reduce testcases posted there and +isolating them. Going through the bugzilla database at +@url{http://gcc.gnu.org/@/bugzilla/} to reduce testcases posted there and add more information (for example, for which version does the testcase work, for which versions does it fail?) is also very helpful. @@ -2876,7 +2949,7 @@ Environment variable forcing standard output to be line buffered (unix). @node Option Index @unnumbered Option Index @command{gfortran}'s command line options are indexed here without any -initial @samp{-} or @samp{--}. Where an option has both positive and +initial @samp{-} or @samp{--}. Where an option has both positive and negative forms (such as -foption and -fno-option), relevant entries in the manual are indexed under the most appropriate form; it may sometimes be useful to look up both forms. diff --git a/gcc/fortran/gfortranspec.c b/gcc/fortran/gfortranspec.c index 4220280eb22..b79f6a25706 100644 --- a/gcc/fortran/gfortranspec.c +++ b/gcc/fortran/gfortranspec.c @@ -271,7 +271,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, verbose = 1; break; - case OPT_fversion: + case OPT__version: printf ("GNU Fortran %s%s\n", pkgversion_string, version_string); printf ("Copyright %s 2010 Free Software Foundation, Inc.\n\n", _("(C)")); @@ -282,7 +282,7 @@ For more information about these matters, see the file named COPYING\n\n")); exit (0); break; - case OPT_fhelp: + case OPT__help: /* Let gcc.c handle this, as it has a really cool facility for handling --help and --verbose --help. */ return; diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c index 044ccd639f2..cbe63cad01b 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -314,12 +314,42 @@ gfc_match_end_interface (void) { if (current_interface.op == INTRINSIC_ASSIGN) - gfc_error ("Expected 'END INTERFACE ASSIGNMENT (=)' at %C"); + { + m = MATCH_ERROR; + gfc_error ("Expected 'END INTERFACE ASSIGNMENT (=)' at %C"); + } else - gfc_error ("Expecting 'END INTERFACE OPERATOR (%s)' at %C", - gfc_op2string (current_interface.op)); + { + const char *s1, *s2; + s1 = gfc_op2string (current_interface.op); + s2 = gfc_op2string (op); + + /* The following if-statements are used to enforce C1202 + from F2003. */ + if ((strcmp(s1, "==") == 0 && strcmp(s2, ".eq.") == 0) + || (strcmp(s1, ".eq.") == 0 && strcmp(s2, "==") == 0)) + break; + if ((strcmp(s1, "/=") == 0 && strcmp(s2, ".ne.") == 0) + || (strcmp(s1, ".ne.") == 0 && strcmp(s2, "/=") == 0)) + break; + if ((strcmp(s1, "<=") == 0 && strcmp(s2, ".le.") == 0) + || (strcmp(s1, ".le.") == 0 && strcmp(s2, "<=") == 0)) + break; + if ((strcmp(s1, "<") == 0 && strcmp(s2, ".lt.") == 0) + || (strcmp(s1, ".lt.") == 0 && strcmp(s2, "<") == 0)) + break; + if ((strcmp(s1, ">=") == 0 && strcmp(s2, ".ge.") == 0) + || (strcmp(s1, ".ge.") == 0 && strcmp(s2, ">=") == 0)) + break; + if ((strcmp(s1, ">") == 0 && strcmp(s2, ".gt.") == 0) + || (strcmp(s1, ".gt.") == 0 && strcmp(s2, ">") == 0)) + break; - m = MATCH_ERROR; + m = MATCH_ERROR; + gfc_error ("Expecting 'END INTERFACE OPERATOR (%s)' at %C, " + "but got %s", s1, s2); + } + } break; @@ -1655,36 +1685,6 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual, } -/* Given a symbol of a formal argument list and an expression, see if - the two are compatible as arguments. Returns nonzero if - compatible, zero if not compatible. */ - -static int -compare_parameter_protected (gfc_symbol *formal, gfc_expr *actual) -{ - if (actual->expr_type != EXPR_VARIABLE) - return 1; - - if (!actual->symtree->n.sym->attr.is_protected) - return 1; - - if (!actual->symtree->n.sym->attr.use_assoc) - return 1; - - if (formal->attr.intent == INTENT_IN - || formal->attr.intent == INTENT_UNKNOWN) - return 1; - - if (!actual->symtree->n.sym->attr.pointer) - return 0; - - if (actual->symtree->n.sym->attr.pointer && formal->attr.pointer) - return 0; - - return 1; -} - - /* Returns the storage size of a symbol (formal argument) or zero if it cannot be determined. */ @@ -2205,27 +2205,20 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal, } /* Check intent = OUT/INOUT for definable actual argument. */ - if ((a->expr->expr_type != EXPR_VARIABLE - || (a->expr->symtree->n.sym->attr.flavor != FL_VARIABLE - && a->expr->symtree->n.sym->attr.flavor != FL_PROCEDURE)) - && (f->sym->attr.intent == INTENT_OUT - || f->sym->attr.intent == INTENT_INOUT)) + if ((f->sym->attr.intent == INTENT_OUT + || f->sym->attr.intent == INTENT_INOUT)) { - if (where) - gfc_error ("Actual argument at %L must be definable as " - "the dummy argument '%s' is INTENT = OUT/INOUT", - &a->expr->where, f->sym->name); - return 0; - } + const char* context = (where + ? _("actual argument to INTENT = OUT/INOUT") + : NULL); - if (!compare_parameter_protected(f->sym, a->expr)) - { - if (where) - gfc_error ("Actual argument at %L is use-associated with " - "PROTECTED attribute and dummy argument '%s' is " - "INTENT = OUT/INOUT", - &a->expr->where,f->sym->name); - return 0; + if (f->sym->attr.pointer + && gfc_check_vardef_context (a->expr, true, context) + == FAILURE) + return 0; + if (gfc_check_vardef_context (a->expr, false, context) + == FAILURE) + return 0; } if ((f->sym->attr.intent == INTENT_OUT diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c index 9c69d7dfc94..625ff033312 100644 --- a/gcc/fortran/intrinsic.c +++ b/gcc/fortran/intrinsic.c @@ -814,6 +814,24 @@ find_sym (gfc_intrinsic_sym *start, int n, const char *name) } +gfc_intrinsic_sym * +gfc_intrinsic_function_by_id (gfc_isym_id id) +{ + gfc_intrinsic_sym *start = functions; + int n = nfunc; + + while (true) + { + gcc_assert (n > 0); + if (id == start->id) + return start; + + start++; + n--; + } +} + + /* Given a name, find a function in the intrinsic function table. Returns NULL if not found. */ @@ -823,10 +841,10 @@ gfc_find_function (const char *name) gfc_intrinsic_sym *sym; sym = find_sym (functions, nfunc, name); - if (!sym) + if (!sym || sym->from_module) sym = find_sym (conversion, nconv, name); - return sym; + return (!sym || sym->from_module) ? NULL : sym; } @@ -836,7 +854,9 @@ gfc_find_function (const char *name) gfc_intrinsic_sym * gfc_find_subroutine (const char *name) { - return find_sym (subroutines, nsub, name); + gfc_intrinsic_sym *sym; + sym = find_sym (subroutines, nsub, name); + return (!sym || sym->from_module) ? NULL : sym; } @@ -849,7 +869,7 @@ gfc_generic_intrinsic (const char *name) gfc_intrinsic_sym *sym; sym = gfc_find_function (name); - return (sym == NULL) ? 0 : sym->generic; + return (!sym || sym->from_module) ? 0 : sym->generic; } @@ -862,7 +882,7 @@ gfc_specific_intrinsic (const char *name) gfc_intrinsic_sym *sym; sym = gfc_find_function (name); - return (sym == NULL) ? 0 : sym->specific; + return (!sym || sym->from_module) ? 0 : sym->specific; } @@ -1014,6 +1034,15 @@ make_noreturn (void) next_sym[-1].noreturn = 1; } + +/* Mark current intrinsic as module intrinsic. */ +static void +make_from_module (void) +{ + if (sizing == SZ_NOTHING) + next_sym[-1].from_module = 1; +} + /* Set the attr.value of the current procedure. */ static void @@ -2607,10 +2636,23 @@ add_functions (void) x, BT_UNKNOWN, 0, REQUIRED); make_generic ("sizeof", GFC_ISYM_SIZEOF, GFC_STD_GNU); - + + /* C_SIZEOF is part of ISO_C_BINDING. */ add_sym_1 ("c_sizeof", GFC_ISYM_C_SIZEOF, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, ii, GFC_STD_F2008, gfc_check_c_sizeof, NULL, NULL, x, BT_UNKNOWN, 0, REQUIRED); + make_from_module(); + + /* COMPILER_OPTIONS and COMPILER_VERSION are part of ISO_FORTRAN_ENV. */ + add_sym_0 ("compiler_options", GFC_ISYM_COMPILER_OPTIONS, CLASS_IMPURE, + ACTUAL_NO, BT_CHARACTER, 1, GFC_STD_F2008, + NULL, gfc_simplify_compiler_options, NULL); + make_from_module(); + + add_sym_0 ("compiler_version", GFC_ISYM_COMPILER_VERSION, CLASS_IMPURE, + ACTUAL_NO, BT_CHARACTER, 1, GFC_STD_F2008, + NULL, gfc_simplify_compiler_version, NULL); + make_from_module(); add_sym_1 ("spacing", GFC_ISYM_SPACING, CLASS_ELEMENTAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F95, gfc_check_x, gfc_simplify_spacing, gfc_resolve_spacing, @@ -3585,6 +3627,19 @@ check_arglist (gfc_actual_arglist **ap, gfc_intrinsic_sym *sym, gfc_typename (&actual->expr->ts)); return FAILURE; } + + /* If the formal argument is INTENT([IN]OUT), check for definability. */ + if (formal->intent == INTENT_INOUT || formal->intent == INTENT_OUT) + { + const char* context = (error_flag + ? _("actual argument to INTENT = OUT/INOUT") + : NULL); + + /* No pointer arguments for intrinsics. */ + if (gfc_check_vardef_context (actual->expr, false, context) + == FAILURE) + return FAILURE; + } } return SUCCESS; @@ -3999,7 +4054,14 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag) name = expr->symtree->n.sym->name; - isym = specific = gfc_find_function (name); + if (expr->symtree->n.sym->intmod_sym_id) + { + int id = expr->symtree->n.sym->intmod_sym_id; + isym = specific = gfc_intrinsic_function_by_id ((gfc_isym_id) id); + } + else + isym = specific = gfc_find_function (name); + if (isym == NULL) { if (!error_flag) diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h index 9818f7a9f47..e9574e8a0e5 100644 --- a/gcc/fortran/intrinsic.h +++ b/gcc/fortran/intrinsic.h @@ -246,6 +246,8 @@ gfc_expr *gfc_simplify_btest (gfc_expr *, gfc_expr *); gfc_expr *gfc_simplify_ceiling (gfc_expr *, gfc_expr *); gfc_expr *gfc_simplify_char (gfc_expr *, gfc_expr *); gfc_expr *gfc_simplify_cmplx (gfc_expr *, gfc_expr *, gfc_expr *); +gfc_expr *gfc_simplify_compiler_options (void); +gfc_expr *gfc_simplify_compiler_version (void); gfc_expr *gfc_simplify_complex (gfc_expr *, gfc_expr *); gfc_expr *gfc_simplify_conjg (gfc_expr *); gfc_expr *gfc_simplify_cos (gfc_expr *); diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index d2b3b94dd38..5c7d4630aaf 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -143,7 +143,7 @@ Some basic guidelines for editing this document: * @code{GMTIME}: GMTIME, Convert time to GMT info * @code{HOSTNM}: HOSTNM, Get system host name * @code{HUGE}: HUGE, Largest number of a kind -* @code{HYPOT}: HYPOT, Euclidian distance function +* @code{HYPOT}: HYPOT, Euclidean distance function * @code{IACHAR}: IACHAR, Code in @acronym{ASCII} collating sequence * @code{IALL}: IALL, Bitwise AND of array elements * @code{IAND}: IAND, Bitwise logical and @@ -156,7 +156,7 @@ Some basic guidelines for editing this document: * @code{IDATE}: IDATE, Current local time (day/month/year) * @code{IEOR}: IEOR, Bitwise logical exclusive or * @code{IERRNO}: IERRNO, Function to get the last system error number -* @code{IMAGE_INDEX}: IMAGE_INDEX, Cosubscript to image index convertion +* @code{IMAGE_INDEX}: IMAGE_INDEX, Cosubscript to image index conversion * @code{INDEX}: INDEX intrinsic, Position of a substring within a string * @code{INT}: INT, Convert to integer type * @code{INT2}: INT2, Convert to 16-bit integer type @@ -1443,7 +1443,7 @@ Inverse function: @ref{TAN} @item @emph{Description}: @code{ATAN2(Y, X)} computes the principal value of the argument function of the complex number @math{X + i Y}. This function can -be used to transform from carthesian into polar coordinates and +be used to transform from Cartesian into polar coordinates and allows to determine the angle in the correct quadrant. @item @emph{Standard}: @@ -1660,7 +1660,7 @@ of the first kind of the orders @var{N1} to @var{N2}. Fortran 2008 and later, negative @var{N} is allowed as GNU extension @item @emph{Class}: -Elemental function, except for the tranformational function +Elemental function, except for the transformational function @code{BESSEL_JN(N1, N2, X)} @item @emph{Syntax}: @@ -1820,7 +1820,7 @@ of the first kind of the orders @var{N1} to @var{N2}. Fortran 2008 and later, negative @var{N} is allowed as GNU extension @item @emph{Class}: -Elemental function, except for the tranformational function +Elemental function, except for the transformational function @code{BESSEL_YN(N1, N2, X)} @item @emph{Syntax}: @@ -4114,7 +4114,7 @@ end program test_exec @item @emph{Note}: Because this intrinsic is implemented in terms of the @code{system()} -function call, its behavior with respect to signalling is processor +function call, its behavior with respect to signaling is processor dependent. In particular, on POSIX-compliant systems, the SIGINT and SIGQUIT signals will be ignored, and the SIGCHLD will be blocked. As such, if the parent process is terminated, the child process might not be @@ -5464,7 +5464,7 @@ END PROGRAM @node GETGID @section @code{GETGID} --- Group ID function @fnindex GETGID -@cindex system, group id +@cindex system, group ID @table @asis @item @emph{Description}: @@ -5541,8 +5541,8 @@ END PROGRAM @node GETPID @section @code{GETPID} --- Process ID function @fnindex GETPID -@cindex system, process id -@cindex process id +@cindex system, process ID +@cindex process ID @table @asis @item @emph{Description}: @@ -5580,7 +5580,7 @@ end program info @node GETUID @section @code{GETUID} --- User ID function @fnindex GETUID -@cindex system, user id +@cindex system, user ID @cindex user id @table @asis @@ -6169,7 +6169,7 @@ The correspondence between characters and their codes is not necessarily the same across different GNU Fortran implementations. @item @emph{Standard}: -Fortan 95 and later, with @var{KIND} argument Fortran 2003 and later +Fortran 95 and later, with @var{KIND} argument Fortran 2003 and later @item @emph{Class}: Elemental function @@ -6285,7 +6285,7 @@ end program test_idate @table @asis @item @emph{Description}: -@code{IEOR} returns the bitwise boolean exclusive-OR of @var{I} and +@code{IEOR} returns the bitwise Boolean exclusive-OR of @var{I} and @var{J}. @item @emph{Standard}: @@ -6351,7 +6351,7 @@ kind. @node IMAGE_INDEX @section @code{IMAGE_INDEX} --- Function that converts a cosubscript to an image index @fnindex IMAGE_INDEX -@cindex coarray, IMAGE_INDEX +@cindex coarray, @code{IMAGE_INDEX} @cindex images, cosubscript to image index conversion @table @asis @@ -6588,7 +6588,7 @@ The return value is a @code{INTEGER(8)} variable. @table @asis @item @emph{Description}: -@code{IOR} returns the bitwise boolean inclusive-OR of @var{I} and +@code{IOR} returns the bitwise Boolean inclusive-OR of @var{I} and @var{J}. @item @emph{Standard}: @@ -6734,7 +6734,7 @@ end program test_irand @node IS_IOSTAT_END @section @code{IS_IOSTAT_END} --- Test for end-of-file value @fnindex IS_IOSTAT_END -@cindex IOSTAT, end of file +@cindex @code{IOSTAT}, end of file @table @asis @item @emph{Description}: @@ -6760,7 +6760,7 @@ Elemental function @item @emph{Return value}: Returns a @code{LOGICAL} of the default kind, which @code{.TRUE.} if @var{I} has the value which indicates an end of file condition for -IOSTAT= specifiers, and is @code{.FALSE.} otherwise. +@code{IOSTAT=} specifiers, and is @code{.FALSE.} otherwise. @item @emph{Example}: @smallexample @@ -6779,7 +6779,7 @@ END PROGRAM @node IS_IOSTAT_EOR @section @code{IS_IOSTAT_EOR} --- Test for end-of-record value @fnindex IS_IOSTAT_EOR -@cindex IOSTAT, end of record +@cindex @code{IOSTAT}, end of record @table @asis @item @emph{Description}: @@ -6805,7 +6805,7 @@ Elemental function @item @emph{Return value}: Returns a @code{LOGICAL} of the default kind, which @code{.TRUE.} if @var{I} has the value which indicates an end of file condition for -IOSTAT= specifiers, and is @code{.FALSE.} otherwise. +@code{IOSTAT=} specifiers, and is @code{.FALSE.} otherwise. @item @emph{Example}: @smallexample @@ -9112,7 +9112,7 @@ end program test_nint @table @asis @item @emph{Description}: -Calculates the Euclidean vector norm (@math{L_2}) norm of +Calculates the Euclidean vector norm (@math{L_2} norm) of of @var{ARRAY} along dimension @var{DIM}. @item @emph{Standard}: @@ -9163,7 +9163,7 @@ END PROGRAM @table @asis @item @emph{Description}: -@code{NOT} returns the bitwise boolean inverse of @var{I}. +@code{NOT} returns the bitwise Boolean inverse of @var{I}. @item @emph{Standard}: Fortran 95 and later @@ -9200,7 +9200,7 @@ argument. @item @emph{Description}: Returns a disassociated pointer. -If @var{MOLD} is present, a dissassociated pointer of the same type is +If @var{MOLD} is present, a disassociated pointer of the same type is returned, otherwise the type is determined by context. In Fortran 95, @var{MOLD} is optional. Please note that Fortran 2003 @@ -9238,7 +9238,7 @@ REAL, POINTER, DIMENSION(:) :: VEC => NULL () @node NUM_IMAGES @section @code{NUM_IMAGES} --- Function that returns the number of images @fnindex NUM_IMAGES -@cindex coarray, NUM_IMAGES +@cindex coarray, @code{NUM_IMAGES} @cindex images, number of @table @asis @@ -9409,7 +9409,7 @@ END PROGRAM @table @asis @item @emph{Description}: -Calculates the partity, i.e. the reduction using @code{.XOR.}, +Calculates the parity, i.e. the reduction using @code{.XOR.}, of @var{MASK} along dimension @var{DIM}. @item @emph{Standard}: @@ -11868,7 +11868,7 @@ end program test_tanh @node THIS_IMAGE @section @code{THIS_IMAGE} --- Function that returns the cosubscript index of this image @fnindex THIS_IMAGE -@cindex coarray, THIS_IMAGE +@cindex coarray, @code{THIS_IMAGE} @cindex images, index of this image @table @asis @@ -12606,6 +12606,10 @@ integer variables used in atomic operations. (Fortran 2008 or later.) Default-kind integer constant to be used as kind parameter when defining logical variables used in atomic operations. (Fortran 2008 or later.) +@item @code{CHARACTER_KINDS}: +Default-kind integer constant array of rank one containing the supported kind +parameters of the @code{CHARACTER} type. (Fortran 2008 or later.) + @item @code{CHARACTER_STORAGE_SIZE}: Size in bits of the character storage unit. @@ -12624,22 +12628,30 @@ Kind type parameters to specify an INTEGER type with a storage size of 16, 32, and 64 bits. It is negative if a target platform does not support the particular kind. (Fortran 2008 or later.) +@item @code{INTEGER_KINDS}: +Default-kind integer constant array of rank one containing the supported kind +parameters of the @code{INTEGER} type. (Fortran 2008 or later.) + @item @code{IOSTAT_END}: -The value assigned to the variable passed to the IOSTAT= specifier of +The value assigned to the variable passed to the @code{IOSTAT=} specifier of an input/output statement if an end-of-file condition occurred. @item @code{IOSTAT_EOR}: -The value assigned to the variable passed to the IOSTAT= specifier of +The value assigned to the variable passed to the @code{IOSTAT=} specifier of an input/output statement if an end-of-record condition occurred. @item @code{IOSTAT_INQUIRE_INTERNAL_UNIT}: Scalar default-integer constant, used by @code{INQUIRE} for the -IOSTAT= specifier to denote an that a unit number identifies an +@code{IOSTAT=} specifier to denote an that a unit number identifies an internal unit. (Fortran 2008 or later.) @item @code{NUMERIC_STORAGE_SIZE}: The size in bits of the numeric storage unit. +@item @code{LOGICAL_KINDS}: +Default-kind integer constant array of rank one containing the supported kind +parameters of the @code{LOGICAL} type. (Fortran 2008 or later.) + @item @code{OUTPUT_UNIT}: Identifies the preconnected unit identified by the asterisk (@code{*}) in @code{WRITE} statement. @@ -12649,6 +12661,10 @@ Kind type parameters to specify a REAL type with a storage size of 32, 64, and 128 bits. It is negative if a target platform does not support the particular kind. (Fortran 2008 or later.) +@item @code{REAL_KINDS}: +Default-kind integer constant array of rank one containing the supported kind +parameters of the @code{REAL} type. (Fortran 2008 or later.) + @item @code{STAT_LOCKED}: Scalar default-integer constant used as STAT= return value by @code{LOCK} to denote that the lock variable is locked by the executing image. (Fortran 2008 @@ -12773,7 +12789,7 @@ a form of two Fortran 90 modules, named @code{OMP_LIB} and @code{OMP_LIB_KINDS}, and in a form of a Fortran @code{include} file named @file{omp_lib.h}. The procedures provided by @code{OMP_LIB} can be found in the @ref{Top,,Introduction,libgomp,GNU OpenMP runtime library} manual, -the named constants defined in the @code{OMP_LIB_KINDS} module are listed +the named constants defined in the modules are listed below. For details refer to the actual @@ -12790,3 +12806,18 @@ named constants: @item @code{omp_nest_lock_kind} @item @code{omp_sched_kind} @end table + +@code{OMP_LIB} provides the scalar default-integer +named constant @code{openmp_version} with a value of the form +@var{yyyymm}, where @code{yyyy} is the year and @var{mm} the month +of the OpenMP version; for OpenMP v3.0 the value is @code{200805}. + +And the following scalar integer named constants of the +kind @code{omp_sched_kind}: + +@table @asis +@item @code{omp_sched_static} +@item @code{omp_sched_dynamic} +@item @code{omp_sched_guided} +@item @code{omp_sched_auto} +@end table diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index 1dfd3bdd920..9e2bc758d37 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -253,7 +253,7 @@ the default width of @code{DOUBLE PRECISION} to 16 bytes if possible, unless @item -fdollar-ok @opindex @code{fdollar-ok} -@cindex $ +@cindex @code{$} @cindex symbol names @cindex character set Allow @samp{$} as a valid non-first character in a symbol name. Symbols @@ -717,7 +717,7 @@ The following example will trigger the warning. @item -Wampersand @opindex @code{Wampersand} @cindex warnings, ampersand -@cindex & +@cindex @code{&} Warn about missing ampersand in continued character constants. The warning is given with @option{-Wampersand}, @option{-pedantic}, @option{-std=f95}, @option{-std=f2003} and @option{-std=f2008}. Note: With no ampersand @@ -851,10 +851,10 @@ is not included in @option{-Wall} but is implied by @option{-Wall -Wextra}. @item -Walign-commons @opindex @code{Walign-commons} -@cindex warnings, alignment of COMMON blocks -@cindex alignment of COMMON blocks +@cindex warnings, alignment of @code{COMMON} blocks +@cindex alignment of @code{COMMON} blocks By default, @command{gfortran} warns about any occasion of variables being -padded for proper alignment inside a COMMON block. This warning can be turned +padded for proper alignment inside a @code{COMMON} block. This warning can be turned off via @option{-Wno-align-commons}. See also @option{-falign-commons}. @item -Werror @@ -929,8 +929,8 @@ debugging options. @cindex directory, options @cindex options, directory search @cindex search path -@cindex INCLUDE directive -@cindex directive, INCLUDE +@cindex @code{INCLUDE} directive +@cindex directive, @code{INCLUDE} These options affect how GNU Fortran searches for files specified by the @code{INCLUDE} directive and where it searches for previously compiled modules. @@ -1313,13 +1313,13 @@ array constructors. The code below requires this option to expand the array at compile time. @smallexample -@code{program test} -@code{implicit none} -@code{integer j} -@code{integer, parameter :: n = 100000} -@code{integer, parameter :: i(n) = (/ (2*j, j = 1, n) /)} -@code{print '(10(I0,1X))', i} -@code{end program test} +program test +implicit none +integer j +integer, parameter :: n = 100000 +integer, parameter :: i(n) = (/ (2*j, j = 1, n) /) +print '(10(I0,1X))', i +end program test @end smallexample @emph{Caution: This option can lead to long compile times and excessively @@ -1427,14 +1427,14 @@ needs to be enabled (e.g. via @option{-ffpe-trap}). @item -falign-commons @opindex @code{falign-commons} -@cindex alignment of COMMON blocks +@cindex alignment of @code{COMMON} blocks By default, @command{gfortran} enforces proper alignment of all variables in a -COMMON block by padding them as needed. On certain platforms this is mandatory, -on others it increases performance. If a COMMON block is not declared with +@code{COMMON} block by padding them as needed. On certain platforms this is mandatory, +on others it increases performance. If a @code{COMMON} block is not declared with consistent data types everywhere, this padding can cause trouble, and -@option{-fno-align-commons } can be used to disable automatic alignment. The -same form of this option should be used for all files that share a COMMON block. -To avoid potential alignment issues in COMMON blocks, it is recommended to order +@option{-fno-align-commons} can be used to disable automatic alignment. The +same form of this option should be used for all files that share a @code{COMMON} block. +To avoid potential alignment issues in @code{COMMON} blocks, it is recommended to order objects from largests to smallest. @item -fno-protect-parens @@ -1442,8 +1442,8 @@ objects from largests to smallest. @cindex re-association of parenthesed expressions By default the parentheses in expression are honored for all optimization levels such that the compiler does not do any re-association. Using -@option{-fno-protect-parens} allows the compiler to reorder REAL and -COMPLEX expressions to produce faster code. Note that for the re-association +@option{-fno-protect-parens} allows the compiler to reorder @code{REAL} and +@code{COMPLEX} expressions to produce faster code. Note that for the re-association optimization @option{-fno-signed-zeros} and @option{-fno-trapping-math} need to be in effect. @end table diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c index afbde0210b4..e80202fab06 100644 --- a/gcc/fortran/io.c +++ b/gcc/fortran/io.c @@ -1505,13 +1505,31 @@ resolve_tag (const io_tag *tag, gfc_expr *e) return FAILURE; } + if (tag == &tag_newunit) + { + if (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: NEWUNIT specifier" + " at %L", &e->where) == FAILURE) + return FAILURE; + } + + /* NEWUNIT, IOSTAT, SIZE and IOMSG are variable definition contexts. */ + if (tag == &tag_newunit || tag == &tag_iostat + || tag == &tag_size || tag == &tag_iomsg) + { + char context[64]; + + sprintf (context, _("%s tag"), tag->name); + if (gfc_check_vardef_context (e, false, context) == FAILURE) + return FAILURE; + } + if (tag == &tag_convert) { if (gfc_notify_std (GFC_STD_GNU, "Extension: CONVERT tag at %L", &e->where) == FAILURE) return FAILURE; } - + return SUCCESS; } @@ -2707,8 +2725,9 @@ gfc_free_dt (gfc_dt *dt) gfc_free_expr (dt->round); gfc_free_expr (dt->blank); gfc_free_expr (dt->decimal); - gfc_free_expr (dt->extra_comma); gfc_free_expr (dt->pos); + gfc_free_expr (dt->dt_io_kind); + /* dt->extra_comma is a link to dt_io_kind if it is set. */ gfc_free (dt); } @@ -2719,6 +2738,11 @@ gfc_try gfc_resolve_dt (gfc_dt *dt, locus *loc) { gfc_expr *e; + io_kind k; + + /* This is set in any case. */ + gcc_assert (dt->dt_io_kind); + k = dt->dt_io_kind->value.iokind; RESOLVE_TAG (&tag_format, dt->format_expr); RESOLVE_TAG (&tag_rec, dt->rec); @@ -2761,16 +2785,13 @@ gfc_resolve_dt (gfc_dt *dt, locus *loc) type character, we assume its really the "format" form of the I/O statement. We set the io_unit to the default unit and format to the character expression. See F95 Standard section 9.4. */ - io_kind k; - k = dt->extra_comma->value.iokind; if (e->ts.type == BT_CHARACTER && (k == M_READ || k == M_PRINT)) { dt->format_expr = dt->io_unit; dt->io_unit = default_unit (k); - /* Free this pointer now so that a warning/error is not triggered - below for the "Extension". */ - gfc_free_expr (dt->extra_comma); + /* Nullify this pointer now so that a warning/error is not + triggered below for the "Extension". */ dt->extra_comma = NULL; } @@ -2790,6 +2811,13 @@ gfc_resolve_dt (gfc_dt *dt, locus *loc) gfc_error ("Internal unit with vector subscript at %L", &e->where); return FAILURE; } + + /* If we are writing, make sure the internal unit can be changed. */ + gcc_assert (k != M_PRINT); + if (k == M_WRITE + && gfc_check_vardef_context (e, false, _("internal unit in WRITE")) + == FAILURE) + return FAILURE; } if (e->rank && e->ts.type != BT_CHARACTER) @@ -2801,10 +2829,36 @@ gfc_resolve_dt (gfc_dt *dt, locus *loc) if (e->expr_type == EXPR_CONSTANT && e->ts.type == BT_INTEGER && mpz_sgn (e->value.integer) < 0) { - gfc_error ("UNIT number in statement at %L must be non-negative", &e->where); + gfc_error ("UNIT number in statement at %L must be non-negative", + &e->where); return FAILURE; } + /* If we are reading and have a namelist, check that all namelist symbols + can appear in a variable definition context. */ + if (k == M_READ && dt->namelist) + { + gfc_namelist* n; + for (n = dt->namelist->namelist; n; n = n->next) + { + gfc_expr* e; + gfc_try t; + + e = gfc_get_variable_expr (gfc_find_sym_in_symtree (n->sym)); + t = gfc_check_vardef_context (e, false, NULL); + gfc_free_expr (e); + + if (t == FAILURE) + { + gfc_error ("NAMELIST '%s' in READ statement at %L contains" + " the symbol '%s' which may not appear in a" + " variable definition context", + dt->namelist->name, loc, n->sym->name); + return FAILURE; + } + } + } + if (dt->extra_comma && gfc_notify_std (GFC_STD_GNU, "Extension: Comma before i/o " "item list at %L", &dt->extra_comma->where) == FAILURE) @@ -2854,6 +2908,7 @@ gfc_resolve_dt (gfc_dt *dt, locus *loc) &dt->format_label->where); return FAILURE; } + return SUCCESS; } @@ -3012,50 +3067,8 @@ match_io_element (io_kind k, gfc_code **cpp) io_kind_name (k)); } - if (m == MATCH_YES) - switch (k) - { - case M_READ: - if (expr->symtree->n.sym->attr.intent == INTENT_IN) - { - gfc_error ("Variable '%s' in input list at %C cannot be " - "INTENT(IN)", expr->symtree->n.sym->name); - m = MATCH_ERROR; - } - - if (gfc_pure (NULL) - && gfc_impure_variable (expr->symtree->n.sym) - && current_dt->io_unit - && current_dt->io_unit->ts.type == BT_CHARACTER) - { - gfc_error ("Cannot read to variable '%s' in PURE procedure at %C", - expr->symtree->n.sym->name); - m = MATCH_ERROR; - } - - if (gfc_check_do_variable (expr->symtree)) - m = MATCH_ERROR; - - break; - - case M_WRITE: - if (current_dt->io_unit - && current_dt->io_unit->ts.type == BT_CHARACTER - && gfc_pure (NULL) - && current_dt->io_unit->expr_type == EXPR_VARIABLE - && gfc_impure_variable (current_dt->io_unit->symtree->n.sym)) - { - gfc_error ("Cannot write to internal file unit '%s' at %C " - "inside a PURE procedure", - current_dt->io_unit->symtree->n.sym->name); - m = MATCH_ERROR; - } - - break; - - default: - break; - } + if (m == MATCH_YES && k == M_READ && gfc_check_do_variable (expr->symtree)) + m = MATCH_ERROR; if (m != MATCH_YES) { @@ -3066,6 +3079,7 @@ match_io_element (io_kind k, gfc_code **cpp) cp = gfc_get_code (); cp->op = EXEC_TRANSFER; cp->expr1 = expr; + cp->ext.dt = current_dt; *cpp = cp; return MATCH_YES; @@ -3657,14 +3671,14 @@ get_io_list: /* Used in check_io_constraints, where no locus is available. */ spec_end = gfc_current_locus; + /* Save the IO kind for later use. */ + dt->dt_io_kind = gfc_get_iokind_expr (&gfc_current_locus, k); + /* Optional leading comma (non-standard). We use a gfc_expr structure here to save the locus. This is used later when resolving transfer statements that might have a format expression without unit number. */ if (!comma_flag && gfc_match_char (',') == MATCH_YES) - { - /* Save the iokind and locus for later use in resolution. */ - dt->extra_comma = gfc_get_iokind_expr (&gfc_current_locus, k); - } + dt->extra_comma = dt->dt_io_kind; io_code = NULL; if (gfc_match_eos () != MATCH_YES) @@ -3973,41 +3987,54 @@ gfc_resolve_inquire (gfc_inquire *inquire) { RESOLVE_TAG (&tag_unit, inquire->unit); RESOLVE_TAG (&tag_file, inquire->file); - RESOLVE_TAG (&tag_iomsg, inquire->iomsg); - RESOLVE_TAG (&tag_iostat, inquire->iostat); - RESOLVE_TAG (&tag_exist, inquire->exist); - RESOLVE_TAG (&tag_opened, inquire->opened); - RESOLVE_TAG (&tag_number, inquire->number); - RESOLVE_TAG (&tag_named, inquire->named); - RESOLVE_TAG (&tag_name, inquire->name); - RESOLVE_TAG (&tag_s_access, inquire->access); - RESOLVE_TAG (&tag_sequential, inquire->sequential); - RESOLVE_TAG (&tag_direct, inquire->direct); - RESOLVE_TAG (&tag_s_form, inquire->form); - RESOLVE_TAG (&tag_formatted, inquire->formatted); - RESOLVE_TAG (&tag_unformatted, inquire->unformatted); - RESOLVE_TAG (&tag_s_recl, inquire->recl); - RESOLVE_TAG (&tag_nextrec, inquire->nextrec); - RESOLVE_TAG (&tag_s_blank, inquire->blank); - RESOLVE_TAG (&tag_s_position, inquire->position); - RESOLVE_TAG (&tag_s_action, inquire->action); - RESOLVE_TAG (&tag_read, inquire->read); - RESOLVE_TAG (&tag_write, inquire->write); - RESOLVE_TAG (&tag_readwrite, inquire->readwrite); - RESOLVE_TAG (&tag_s_delim, inquire->delim); - RESOLVE_TAG (&tag_s_pad, inquire->pad); - RESOLVE_TAG (&tag_s_encoding, inquire->encoding); - RESOLVE_TAG (&tag_s_round, inquire->round); - RESOLVE_TAG (&tag_iolength, inquire->iolength); - RESOLVE_TAG (&tag_convert, inquire->convert); - RESOLVE_TAG (&tag_strm_out, inquire->strm_pos); - RESOLVE_TAG (&tag_s_async, inquire->asynchronous); - RESOLVE_TAG (&tag_s_sign, inquire->sign); - RESOLVE_TAG (&tag_s_round, inquire->round); - RESOLVE_TAG (&tag_pending, inquire->pending); - RESOLVE_TAG (&tag_size, inquire->size); RESOLVE_TAG (&tag_id, inquire->id); + /* For INQUIRE, all tags except FILE, ID and UNIT are variable definition + contexts. Thus, use an extended RESOLVE_TAG macro for that. */ +#define INQUIRE_RESOLVE_TAG(tag, expr) \ + RESOLVE_TAG (tag, expr); \ + if (expr) \ + { \ + char context[64]; \ + sprintf (context, _("%s tag with INQUIRE"), (tag)->name); \ + if (gfc_check_vardef_context ((expr), false, context) == FAILURE) \ + return FAILURE; \ + } + INQUIRE_RESOLVE_TAG (&tag_iomsg, inquire->iomsg); + INQUIRE_RESOLVE_TAG (&tag_iostat, inquire->iostat); + INQUIRE_RESOLVE_TAG (&tag_exist, inquire->exist); + INQUIRE_RESOLVE_TAG (&tag_opened, inquire->opened); + INQUIRE_RESOLVE_TAG (&tag_number, inquire->number); + INQUIRE_RESOLVE_TAG (&tag_named, inquire->named); + INQUIRE_RESOLVE_TAG (&tag_name, inquire->name); + INQUIRE_RESOLVE_TAG (&tag_s_access, inquire->access); + INQUIRE_RESOLVE_TAG (&tag_sequential, inquire->sequential); + INQUIRE_RESOLVE_TAG (&tag_direct, inquire->direct); + INQUIRE_RESOLVE_TAG (&tag_s_form, inquire->form); + INQUIRE_RESOLVE_TAG (&tag_formatted, inquire->formatted); + INQUIRE_RESOLVE_TAG (&tag_unformatted, inquire->unformatted); + INQUIRE_RESOLVE_TAG (&tag_s_recl, inquire->recl); + INQUIRE_RESOLVE_TAG (&tag_nextrec, inquire->nextrec); + INQUIRE_RESOLVE_TAG (&tag_s_blank, inquire->blank); + INQUIRE_RESOLVE_TAG (&tag_s_position, inquire->position); + INQUIRE_RESOLVE_TAG (&tag_s_action, inquire->action); + INQUIRE_RESOLVE_TAG (&tag_read, inquire->read); + INQUIRE_RESOLVE_TAG (&tag_write, inquire->write); + INQUIRE_RESOLVE_TAG (&tag_readwrite, inquire->readwrite); + INQUIRE_RESOLVE_TAG (&tag_s_delim, inquire->delim); + INQUIRE_RESOLVE_TAG (&tag_s_pad, inquire->pad); + INQUIRE_RESOLVE_TAG (&tag_s_encoding, inquire->encoding); + INQUIRE_RESOLVE_TAG (&tag_s_round, inquire->round); + INQUIRE_RESOLVE_TAG (&tag_iolength, inquire->iolength); + INQUIRE_RESOLVE_TAG (&tag_convert, inquire->convert); + INQUIRE_RESOLVE_TAG (&tag_strm_out, inquire->strm_pos); + INQUIRE_RESOLVE_TAG (&tag_s_async, inquire->asynchronous); + INQUIRE_RESOLVE_TAG (&tag_s_sign, inquire->sign); + INQUIRE_RESOLVE_TAG (&tag_s_round, inquire->round); + INQUIRE_RESOLVE_TAG (&tag_pending, inquire->pending); + INQUIRE_RESOLVE_TAG (&tag_size, inquire->size); +#undef INQUIRE_RESOLVE_TAG + if (gfc_reference_st_label (inquire->err, ST_LABEL_TARGET) == FAILURE) return FAILURE; diff --git a/gcc/fortran/iso-c-binding.def b/gcc/fortran/iso-c-binding.def index a529368765c..4cb7c2333d9 100644 --- a/gcc/fortran/iso-c-binding.def +++ b/gcc/fortran/iso-c-binding.def @@ -39,6 +39,10 @@ along with GCC; see the file COPYING3. If not see # define NAMED_CHARKNDCST(a,b,c) #endif +#ifndef NAMED_FUNCTION +# define NAMED_FUNCTION(a,b,c,d) +#endif + /* The arguments to NAMED_*CST are: -- an internal name -- the symbol name in the module, as seen by Fortran code @@ -162,6 +166,15 @@ PROCEDURE (ISOCBINDING_LOC, "c_loc") PROCEDURE (ISOCBINDING_FUNLOC, "c_funloc") PROCEDURE (ISOCBINDING_F_PROCPOINTER, "c_f_procpointer") +/* The arguments to NAMED_FUNCTIONS are: + -- the ISYM + -- the symbol name in the module, as seen by Fortran code + -- the Fortran standard */ + +NAMED_FUNCTION (ISOCBINDING_C_SIZEOF, "c_sizeof", \ + GFC_ISYM_C_SIZEOF, GFC_STD_F2008) + + #undef NAMED_INTCST #undef NAMED_REALCST #undef NAMED_CMPXCST @@ -170,3 +183,4 @@ PROCEDURE (ISOCBINDING_F_PROCPOINTER, "c_f_procpointer") #undef NAMED_CHARKNDCST #undef DERIVED_TYPE #undef PROCEDURE +#undef NAMED_FUNCTION diff --git a/gcc/fortran/iso-fortran-env.def b/gcc/fortran/iso-fortran-env.def index 6c009f1c8fd..3586f076926 100644 --- a/gcc/fortran/iso-fortran-env.def +++ b/gcc/fortran/iso-fortran-env.def @@ -19,6 +19,18 @@ along with GCC; see the file COPYING3. If not see /* This file contains the definition of the named integer constants provided by the Fortran 2003 ISO_FORTRAN_ENV intrinsic module. */ +#ifndef NAMED_INTCST +# define NAMED_INTCST(a,b,c,d) +#endif + +#ifndef NAMED_KINDARRAY +# define NAMED_KINDARRAY(a,b,c,d) +#endif + +#ifndef NAMED_FUNCTION +# define NAMED_FUNCTION(a,b,c,d) +#endif + /* The arguments to NAMED_INTCST are: -- an internal name -- the symbol name in the module, as seen by Fortran code @@ -50,7 +62,7 @@ NAMED_INTCST (ISOFORTRANENV_IOSTAT_END, "iostat_end", LIBERROR_END, \ NAMED_INTCST (ISOFORTRANENV_IOSTAT_EOR, "iostat_eor", LIBERROR_EOR, \ GFC_STD_F2003) NAMED_INTCST (ISOFORTRANENV_IOSTAT_INQUIRE_INTERNAL_UNIT, \ - "iostat_inquire_internal_unit", GFC_INQUIRE_INTERNAL_UNIT, \ + "iostat_inquire_internal_unit", LIBERROR_INQUIRE_INTERNAL_UNIT, \ GFC_STD_F2008) NAMED_INTCST (ISOFORTRANENV_NUMERIC_STORAGE_SIZE, "numeric_storage_size", \ gfc_numeric_storage_size, GFC_STD_F2003) @@ -72,3 +84,33 @@ NAMED_INTCST (ISOFORTRANENV_FILE_STAT_STOPPED_IMAGE, "stat_stopped_image", \ NAMED_INTCST (ISOFORTRANENV_FILE_STAT_UNLOCKED, "stat_unlocked", \ GFC_STAT_UNLOCKED, GFC_STD_F2008) + +/* The arguments to NAMED_KINDARRAY are: + -- an internal name + -- the symbol name in the module, as seen by Fortran code + -- the gfortran variable containing the information + -- the Fortran standard */ + +NAMED_KINDARRAY (ISOFORTRAN_CHARACTER_KINDS, "character_kinds", \ + gfc_character_kinds, GFC_STD_F2008) +NAMED_KINDARRAY (ISOFORTRAN_INTEGER_KINDS, "integer_kinds", \ + gfc_integer_kinds, GFC_STD_F2008) +NAMED_KINDARRAY (ISOFORTRAN_LOGICAL_KINDS, "logical_kinds", \ + gfc_logical_kinds, GFC_STD_F2008) +NAMED_KINDARRAY (ISOFORTRAN_REAL_KINDS, "real_kinds", \ + gfc_real_kinds, GFC_STD_F2008) + +/* The arguments to NAMED_FUNCTIONS are: + -- the ISYM + -- the symbol name in the module, as seen by Fortran code + -- the Fortran standard */ + +NAMED_FUNCTION (ISOFORTRAN_COMPILER_OPTIONS, "compiler_options", \ + GFC_ISYM_COMPILER_OPTIONS, GFC_STD_F2008) +NAMED_FUNCTION (ISOFORTRAN_COMPILER_VERSION, "compiler_version", \ + GFC_ISYM_COMPILER_VERSION, GFC_STD_F2008) + + +#undef NAMED_INTCST +#undef NAMED_KINDARRAY +#undef NAMED_FUNCTION diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt index a5a785b1b7c..d523bdfe66c 100644 --- a/gcc/fortran/lang.opt +++ b/gcc/fortran/lang.opt @@ -25,6 +25,96 @@ Language Fortran +-all-warnings +Fortran Alias(Wall) + +-assert +Fortran Separate Alias(A) + +-assert= +Fortran Joined Alias(A) + +-comments +Fortran Alias(C) + +-comments-in-macros +Fortran Alias(CC) + +-define-macro +Fortran Separate Alias(D) + +-define-macro= +Fortran Joined Alias(D) + +-dependencies +Fortran Alias(M) + +-dump +Fortran Separate Alias(d) + +-dump= +Fortran Joined Alias(d) + +-include-barrier +Fortran Alias(I, -) + +-include-directory +Fortran Separate Alias(I) + +-include-directory= +Fortran Joined Alias(I) + +-include-directory-after +Fortran Separate Alias(idirafter) + +-include-directory-after= +Fortran Joined Alias(idirafter) + +-include-prefix +Fortran Separate Alias(iprefix) + +-include-prefix= +Fortran JoinedOrMissing Alias(iprefix) + +-no-line-commands +Fortran Alias(P) + +-no-standard-includes +Fortran Alias(nostdinc) + +-output +Fortran Separate Alias(o) + +-output= +Fortran Joined Alias(o) + +-preprocess +Fortran Undocumented Alias(E) + +-print-missing-file-dependencies +Fortran Alias(MG) + +-trace-includes +Fortran Alias(H) + +-undefine-macro +Fortran Separate Alias(U) + +-undefine-macro= +Fortran Joined Alias(U) + +-user-dependencies +Fortran Alias(MM) + +-verbose +Fortran Alias(v) + +-write-dependencies +Fortran NoDriverArg Separate Alias(MD) + +-write-user-dependencies +Fortran NoDriverArg Separate Alias(MMD) + A Fortran Joined Separate ; Documented in C diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h index d9216d30149..e26cbf9b5f4 100644 --- a/gcc/fortran/libgfortran.h +++ b/gcc/fortran/libgfortran.h @@ -93,6 +93,7 @@ typedef enum LIBERROR_DIRECT_EOR, LIBERROR_SHORT_RECORD, LIBERROR_CORRUPT_FILE, + LIBERROR_INQUIRE_INTERNAL_UNIT, /* Must be different from STAT_STOPPED_IMAGE. */ LIBERROR_LAST /* Not a real error, the last error # + 1. */ } libgfortran_error_codes; @@ -102,8 +103,7 @@ typedef enum GFC_STAT_UNLOCKED = 0, GFC_STAT_LOCKED, GFC_STAT_LOCKED_OTHER_IMAGE, - GFC_STAT_STOPPED_IMAGE, - GFC_INQUIRE_INTERNAL_UNIT /* Must be different from STAT_STOPPED_IMAGE. */ + GFC_STAT_STOPPED_IMAGE } libgfortran_stat_codes; diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c index ff0ef44f64a..836c95cc2df 100644 --- a/gcc/fortran/match.c +++ b/gcc/fortran/match.c @@ -978,13 +978,6 @@ gfc_match_iterator (gfc_iterator *iter, int init_flag) goto cleanup; } - if (var->symtree->n.sym->attr.intent == INTENT_IN) - { - gfc_error ("Loop variable '%s' at %C cannot be INTENT(IN)", - var->symtree->n.sym->name); - goto cleanup; - } - gfc_match_char ('='); var->symtree->n.sym->attr.implied_index = 1; @@ -1847,9 +1840,7 @@ gfc_match_associate (void) /* The `variable' field is left blank for now; because the target is not yet resolved, we can't use gfc_has_vector_subscript to determine it - for now. Instead, if the symbol is matched as variable, this field - is set -- and during resolution we check that. */ - newAssoc->variable = 0; + for now. This is set during resolution. */ /* Put it into the list. */ newAssoc->next = new_st.ext.block.assoc; @@ -3166,12 +3157,6 @@ gfc_match_nullify (void) if (gfc_check_do_variable (p->symtree)) goto cleanup; - if (gfc_pure (NULL) && gfc_impure_variable (p->symtree->n.sym)) - { - gfc_error ("Illegal variable in NULLIFY at %C for a PURE procedure"); - goto cleanup; - } - /* build ' => NULL() '. */ e = gfc_get_null_expr (&gfc_current_locus); @@ -4523,6 +4508,7 @@ select_type_set_tmp (gfc_typespec *ts) &tmp->n.sym->as, false); tmp->n.sym->attr.class_ok = 1; } + tmp->n.sym->attr.select_type_temporary = 1; /* Add an association for it, so the rest of the parser knows it is an associate-name. The target will be set during resolution. */ diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c index e9a8625212d..c90fe0d298f 100644 --- a/gcc/fortran/module.c +++ b/gcc/fortran/module.c @@ -5207,6 +5207,38 @@ gfc_dump_module (const char *name, int dump_flag) } +static void +create_intrinsic_function (const char *name, gfc_isym_id id, + const char *modname, intmod_id module) +{ + gfc_intrinsic_sym *isym; + gfc_symtree *tmp_symtree; + gfc_symbol *sym; + + tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, name); + if (tmp_symtree) + { + if (strcmp (modname, tmp_symtree->n.sym->module) == 0) + return; + gfc_error ("Symbol '%s' already declared", name); + } + + gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false); + sym = tmp_symtree->n.sym; + + isym = gfc_intrinsic_function_by_id (id); + gcc_assert (isym); + + sym->attr.flavor = FL_PROCEDURE; + sym->attr.intrinsic = 1; + + sym->module = gfc_get_string (modname); + sym->attr.use_assoc = 1; + sym->from_intmod = module; + sym->intmod_sym_id = id; +} + + /* Import the intrinsic ISO_C_BINDING module, generating symbols in the current namespace for all named constants, pointer types, and procedures in the module unless the only clause was used or a rename @@ -5252,14 +5284,45 @@ import_iso_c_binding_module (void) { u->found = 1; found = true; - generate_isocbinding_symbol (iso_c_module_name, - (iso_c_binding_symbol) i, - u->local_name); + switch (i) + { +#define NAMED_FUNCTION(a,b,c,d) \ + case a: \ + create_intrinsic_function (u->local_name[0] ? u->local_name \ + : u->use_name, \ + (gfc_isym_id) c, \ + iso_c_module_name, \ + INTMOD_ISO_C_BINDING); \ + break; +#include "iso-c-binding.def" +#undef NAMED_FUNCTION + + default: + generate_isocbinding_symbol (iso_c_module_name, + (iso_c_binding_symbol) i, + u->local_name[0] ? u->local_name + : u->use_name); + } } if (!found && !only_flag) - generate_isocbinding_symbol (iso_c_module_name, - (iso_c_binding_symbol) i, NULL); + switch (i) + { +#define NAMED_FUNCTION(a,b,c,d) \ + case a: \ + if ((gfc_option.allow_std & d) == 0) \ + continue; \ + create_intrinsic_function (b, (gfc_isym_id) c, \ + iso_c_module_name, \ + INTMOD_ISO_C_BINDING); \ + break; +#include "iso-c-binding.def" +#undef NAMED_FUNCTION + + default: + generate_isocbinding_symbol (iso_c_module_name, + (iso_c_binding_symbol) i, NULL); + } } for (u = gfc_rename_list; u; u = u->next) @@ -5305,6 +5368,49 @@ create_int_parameter (const char *name, int value, const char *modname, } +/* Value is already contained by the array constructor, but not + yet the shape. */ + +static void +create_int_parameter_array (const char *name, int size, gfc_expr *value, + const char *modname, intmod_id module, int id) +{ + gfc_symtree *tmp_symtree; + gfc_symbol *sym; + + tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, name); + if (tmp_symtree != NULL) + { + if (strcmp (modname, tmp_symtree->n.sym->module) == 0) + return; + else + gfc_error ("Symbol '%s' already declared", name); + } + + gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false); + sym = tmp_symtree->n.sym; + + sym->module = gfc_get_string (modname); + sym->attr.flavor = FL_PARAMETER; + sym->ts.type = BT_INTEGER; + sym->ts.kind = gfc_default_integer_kind; + sym->attr.use_assoc = 1; + sym->from_intmod = module; + sym->intmod_sym_id = id; + sym->attr.dimension = 1; + sym->as = gfc_get_array_spec (); + sym->as->rank = 1; + sym->as->type = AS_EXPLICIT; + sym->as->lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1); + sym->as->upper[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, size); + + sym->value = value; + sym->value->shape = gfc_get_shape (1); + mpz_init_set_ui (sym->value->shape[0], size); +} + + + /* USE the ISO_FORTRAN_ENV intrinsic module. */ static void @@ -5314,12 +5420,19 @@ use_iso_fortran_env_module (void) gfc_use_rename *u; gfc_symbol *mod_sym; gfc_symtree *mod_symtree; - int i; + gfc_expr *expr; + int i, j; intmod_sym symbol[] = { #define NAMED_INTCST(a,b,c,d) { a, b, 0, d }, #include "iso-fortran-env.def" #undef NAMED_INTCST +#define NAMED_KINDARRAY(a,b,c,d) { a, b, 0, d }, +#include "iso-fortran-env.def" +#undef NAMED_KINDARRAY +#define NAMED_FUNCTION(a,b,c,d) { a, b, c, d }, +#include "iso-fortran-env.def" +#undef NAMED_FUNCTION { ISOFORTRANENV_INVALID, NULL, -1234, 0 } }; i = 0; @@ -5371,10 +5484,49 @@ use_iso_fortran_env_module (void) gfc_option.flag_default_integer ? "-fdefault-integer-8" : "-fdefault-real-8"); + switch (symbol[i].id) + { +#define NAMED_INTCST(a,b,c,d) \ + case a: +#include "iso-fortran-env.def" +#undef NAMED_INTCST + create_int_parameter (u->local_name[0] ? u->local_name + : u->use_name, + symbol[i].value, mod, + INTMOD_ISO_FORTRAN_ENV, symbol[i].id); + break; + +#define NAMED_KINDARRAY(a,b,KINDS,d) \ + case a:\ + expr = gfc_get_array_expr (BT_INTEGER, \ + gfc_default_integer_kind,\ + NULL); \ + for (j = 0; KINDS[j].kind != 0; j++) \ + gfc_constructor_append_expr (&expr->value.constructor, \ + gfc_get_int_expr (gfc_default_integer_kind, NULL, \ + KINDS[j].kind), NULL); \ + create_int_parameter_array (u->local_name[0] ? u->local_name \ + : u->use_name, \ + j, expr, mod, \ + INTMOD_ISO_FORTRAN_ENV, \ + symbol[i].id); \ + break; +#include "iso-fortran-env.def" +#undef NAMED_KINDARRAY - create_int_parameter (u->local_name[0] ? u->local_name : u->use_name, - symbol[i].value, mod, - INTMOD_ISO_FORTRAN_ENV, symbol[i].id); +#define NAMED_FUNCTION(a,b,c,d) \ + case a: +#include "iso-fortran-env.def" +#undef NAMED_FUNCTION + create_intrinsic_function (u->local_name[0] ? u->local_name + : u->use_name, + (gfc_isym_id) symbol[i].value, mod, + INTMOD_ISO_FORTRAN_ENV); + break; + + default: + gcc_unreachable (); + } } } @@ -5391,8 +5543,42 @@ use_iso_fortran_env_module (void) gfc_option.flag_default_integer ? "-fdefault-integer-8" : "-fdefault-real-8"); - create_int_parameter (symbol[i].name, symbol[i].value, mod, - INTMOD_ISO_FORTRAN_ENV, symbol[i].id); + switch (symbol[i].id) + { +#define NAMED_INTCST(a,b,c,d) \ + case a: +#include "iso-fortran-env.def" +#undef NAMED_INTCST + create_int_parameter (symbol[i].name, symbol[i].value, mod, + INTMOD_ISO_FORTRAN_ENV, symbol[i].id); + break; + +#define NAMED_KINDARRAY(a,b,KINDS,d) \ + case a:\ + expr = gfc_get_array_expr (BT_INTEGER, gfc_default_integer_kind, \ + NULL); \ + for (j = 0; KINDS[j].kind != 0; j++) \ + gfc_constructor_append_expr (&expr->value.constructor, \ + gfc_get_int_expr (gfc_default_integer_kind, NULL, \ + KINDS[j].kind), NULL); \ + create_int_parameter_array (symbol[i].name, j, expr, mod, \ + INTMOD_ISO_FORTRAN_ENV, symbol[i].id);\ + break; +#include "iso-fortran-env.def" +#undef NAMED_KINDARRAY + +#define NAMED_FUNCTION(a,b,c,d) \ + case a: +#include "iso-fortran-env.def" +#undef NAMED_FUNCTION + create_intrinsic_function (symbol[i].name, + (gfc_isym_id) symbol[i].value, mod, + INTMOD_ISO_FORTRAN_ENV); + break; + + default: + gcc_unreachable (); + } } } diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c index b07632d951c..f6ceae91903 100644 --- a/gcc/fortran/primary.c +++ b/gcc/fortran/primary.c @@ -2007,7 +2007,6 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts) if (expr->expr_type != EXPR_VARIABLE && expr->expr_type != EXPR_FUNCTION) gfc_internal_error ("gfc_variable_attr(): Expression isn't a variable"); - ref = expr->ref; sym = expr->symtree->n.sym; attr = sym->attr; @@ -2031,7 +2030,7 @@ gfc_variable_attr (gfc_expr *expr, gfc_typespec *ts) if (ts != NULL && expr->ts.type == BT_UNKNOWN) *ts = sym->ts; - for (; ref; ref = ref->next) + for (ref = expr->ref; ref; ref = ref->next) switch (ref->type) { case REF_ARRAY: @@ -2986,13 +2985,7 @@ match_variable (gfc_expr **result, int equiv_flag, int host_flag) switch (sym->attr.flavor) { case FL_VARIABLE: - if (sym->attr.is_protected && sym->attr.use_assoc) - { - gfc_error ("Assigning to PROTECTED variable at %C"); - return MATCH_ERROR; - } - if (sym->assoc) - sym->assoc->variable = 1; + /* Everything is alright. */ break; case FL_UNKNOWN: @@ -3024,22 +3017,24 @@ match_variable (gfc_expr **result, int equiv_flag, int host_flag) case FL_PARAMETER: if (equiv_flag) - gfc_error ("Named constant at %C in an EQUIVALENCE"); - else - gfc_error ("Cannot assign to a named constant at %C"); - return MATCH_ERROR; + { + gfc_error ("Named constant at %C in an EQUIVALENCE"); + return MATCH_ERROR; + } + /* Otherwise this is checked for and an error given in the + variable definition context checks. */ break; case FL_PROCEDURE: /* Check for a nonrecursive function result variable. */ if (sym->attr.function - && !sym->attr.external - && sym->result == sym - && (gfc_is_function_return_value (sym, gfc_current_ns) - || (sym->attr.entry - && sym->ns == gfc_current_ns) - || (sym->attr.entry - && sym->ns == gfc_current_ns->parent))) + && !sym->attr.external + && sym->result == sym + && (gfc_is_function_return_value (sym, gfc_current_ns) + || (sym->attr.entry + && sym->ns == gfc_current_ns) + || (sym->attr.entry + && sym->ns == gfc_current_ns->parent))) { /* If a function result is a derived type, then the derived type may still have to be resolved. */ diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 2d5e04f22d5..4958cbde185 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -1396,7 +1396,7 @@ is_illegal_recursion (gfc_symbol* sym, gfc_namespace* context) static gfc_try resolve_intrinsic (gfc_symbol *sym, locus *loc) { - gfc_intrinsic_sym* isym; + gfc_intrinsic_sym* isym = NULL; const char* symstd; if (sym->formal) @@ -1407,7 +1407,12 @@ resolve_intrinsic (gfc_symbol *sym, locus *loc) gfc_find_subroutine directly to check whether it is a function or subroutine. */ - if ((isym = gfc_find_function (sym->name))) + if (sym->intmod_sym_id) + isym = gfc_intrinsic_function_by_id ((gfc_isym_id) sym->intmod_sym_id); + else + isym = gfc_find_function (sym->name); + + if (isym) { if (sym->ts.type != BT_UNKNOWN && gfc_option.warn_surprising && !sym->attr.implicit_type) @@ -2859,8 +2864,6 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_actual_arglist *args, /* Resolve a function call, which means resolving the arguments, then figuring out which entity the name refers to. */ -/* TODO: Check procedure arguments so that an INTENT(IN) isn't passed - to INTENT(OUT) or INTENT(INOUT). */ static gfc_try resolve_function (gfc_expr *expr) @@ -6131,12 +6134,9 @@ gfc_resolve_iterator (gfc_iterator *iter, bool real_ok) == FAILURE) return FAILURE; - if (gfc_pure (NULL) && gfc_impure_variable (iter->var->symtree->n.sym)) - { - gfc_error ("Cannot assign to loop variable in PURE procedure at %L", - &iter->var->where); - return FAILURE; - } + if (gfc_check_vardef_context (iter->var, false, _("iterator variable")) + == FAILURE) + return FAILURE; if (gfc_resolve_iterator_expr (iter->start, real_ok, "Start expression in DO loop") == FAILURE) @@ -6331,14 +6331,11 @@ static gfc_try resolve_deallocate_expr (gfc_expr *e) { symbol_attribute attr; - int allocatable, pointer, check_intent_in; + int allocatable, pointer; gfc_ref *ref; gfc_symbol *sym; gfc_component *c; - /* Check INTENT(IN), unless the object is a sub-component of a pointer. */ - check_intent_in = 1; - if (gfc_resolve_expr (e) == FAILURE) return FAILURE; @@ -6359,9 +6356,6 @@ resolve_deallocate_expr (gfc_expr *e) } for (ref = e->ref; ref; ref = ref->next) { - if (pointer) - check_intent_in = 0; - switch (ref->type) { case REF_ARRAY: @@ -6399,12 +6393,11 @@ resolve_deallocate_expr (gfc_expr *e) return FAILURE; } - if (check_intent_in && sym->attr.intent == INTENT_IN) - { - gfc_error ("Cannot deallocate INTENT(IN) variable '%s' at %L", - sym->name, &e->where); - return FAILURE; - } + if (pointer + && gfc_check_vardef_context (e, true, _("DEALLOCATE object")) == FAILURE) + return FAILURE; + if (gfc_check_vardef_context (e, false, _("DEALLOCATE object")) == FAILURE) + return FAILURE; if (e->ts.type == BT_CLASS) { @@ -6464,6 +6457,31 @@ gfc_expr_to_initialize (gfc_expr *e) } +/* If the last ref of an expression is an array ref, return a copy of the + expression with that one removed. Otherwise, a copy of the original + expression. This is used for allocate-expressions and pointer assignment + LHS, where there may be an array specification that needs to be stripped + off when using gfc_check_vardef_context. */ + +static gfc_expr* +remove_last_array_ref (gfc_expr* e) +{ + gfc_expr* e2; + gfc_ref** r; + + e2 = gfc_copy_expr (e); + for (r = &e2->ref; *r; r = &(*r)->next) + if ((*r)->type == REF_ARRAY && !(*r)->next) + { + gfc_free_ref_list (*r); + *r = NULL; + break; + } + + return e2; +} + + /* Used in resolve_allocate_expr to check that a allocation-object and a source-expr are conformable. This does not catch all possible cases; in particular a runtime checking is needed. */ @@ -6526,17 +6544,16 @@ conformable_arrays (gfc_expr *e1, gfc_expr *e2) static gfc_try resolve_allocate_expr (gfc_expr *e, gfc_code *code) { - int i, pointer, allocatable, dimension, check_intent_in, is_abstract; + int i, pointer, allocatable, dimension, is_abstract; int codimension; symbol_attribute attr; gfc_ref *ref, *ref2; + gfc_expr *e2; gfc_array_ref *ar; gfc_symbol *sym = NULL; gfc_alloc *a; gfc_component *c; - - /* Check INTENT(IN), unless the object is a sub-component of a pointer. */ - check_intent_in = 1; + gfc_try t; /* Mark the ultimost array component as being in allocate to allow DIMEN_STAR checking of coarrays. */ @@ -6588,9 +6605,6 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code) for (ref = e->ref; ref; ref2 = ref, ref = ref->next) { - if (pointer) - check_intent_in = 0; - switch (ref->type) { case REF_ARRAY: @@ -6677,12 +6691,18 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code) goto failure; } - if (check_intent_in && sym->attr.intent == INTENT_IN) - { - gfc_error ("Cannot allocate INTENT(IN) variable '%s' at %L", - sym->name, &e->where); - goto failure; - } + /* In the variable definition context checks, gfc_expr_attr is used + on the expression. This is fooled by the array specification + present in e, thus we have to eliminate that one temporarily. */ + e2 = remove_last_array_ref (e); + t = SUCCESS; + if (t == SUCCESS && pointer) + t = gfc_check_vardef_context (e2, true, _("ALLOCATE object")); + if (t == SUCCESS) + t = gfc_check_vardef_context (e2, false, _("ALLOCATE object")); + gfc_free_expr (e2); + if (t == FAILURE) + goto failure; if (!code->expr3) { @@ -6733,9 +6753,9 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code) if (pointer || (dimension == 0 && codimension == 0)) goto success; - /* Make sure the next-to-last reference node is an array specification. */ + /* Make sure the last reference node is an array specifiction. */ - if (ref2 == NULL || ref2->type != REF_ARRAY || ref2->u.ar.type == AR_FULL + if (!ref2 || ref2->type != REF_ARRAY || ref2->u.ar.type == AR_FULL || (dimension && ref2->u.ar.dimen == 0)) { gfc_error ("Array specification required in ALLOCATE statement " @@ -6846,20 +6866,13 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn) gfc_expr *stat, *errmsg, *pe, *qe; gfc_alloc *a, *p, *q; - stat = code->expr1 ? code->expr1 : NULL; - - errmsg = code->expr2 ? code->expr2 : NULL; + stat = code->expr1; + errmsg = code->expr2; /* Check the stat variable. */ if (stat) { - if (stat->symtree->n.sym->attr.intent == INTENT_IN) - gfc_error ("Stat-variable '%s' at %L cannot be INTENT(IN)", - stat->symtree->n.sym->name, &stat->where); - - if (gfc_pure (NULL) && gfc_impure_variable (stat->symtree->n.sym)) - gfc_error ("Illegal stat-variable at %L for a PURE procedure", - &stat->where); + gfc_check_vardef_context (stat, false, _("STAT variable")); if ((stat->ts.type != BT_INTEGER && !(stat->ref && (stat->ref->type == REF_ARRAY @@ -6902,13 +6915,7 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn) gfc_warning ("ERRMSG at %L is useless without a STAT tag", &errmsg->where); - if (errmsg->symtree->n.sym->attr.intent == INTENT_IN) - gfc_error ("Errmsg-variable '%s' at %L cannot be INTENT(IN)", - errmsg->symtree->n.sym->name, &errmsg->where); - - if (gfc_pure (NULL) && gfc_impure_variable (errmsg->symtree->n.sym)) - gfc_error ("Illegal errmsg-variable at %L for a PURE procedure", - &errmsg->where); + gfc_check_vardef_context (errmsg, false, _("ERRMSG variable")); if ((errmsg->ts.type != BT_CHARACTER && !(errmsg->ref @@ -7539,7 +7546,6 @@ static void resolve_assoc_var (gfc_symbol* sym, bool resolve_target) { gfc_expr* target; - bool to_var; gcc_assert (sym->assoc); gcc_assert (sym->attr.flavor == FL_VARIABLE); @@ -7569,26 +7575,16 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target) sym->attr.target = (tsym->attr.target || tsym->attr.pointer); } - sym->ts = target->ts; + /* Get type if this was not already set. Note that it can be + some other type than the target in case this is a SELECT TYPE + selector! So we must not update when the type is already there. */ + if (sym->ts.type == BT_UNKNOWN) + sym->ts = target->ts; gcc_assert (sym->ts.type != BT_UNKNOWN); /* See if this is a valid association-to-variable. */ - to_var = (target->expr_type == EXPR_VARIABLE - && !gfc_has_vector_subscript (target)); - if (sym->assoc->variable && !to_var) - { - if (target->expr_type == EXPR_VARIABLE) - gfc_error ("'%s' at %L associated to vector-indexed target can not" - " be used in a variable definition context", - sym->name, &sym->declared_at); - else - gfc_error ("'%s' at %L associated to expression can not" - " be used in a variable definition context", - sym->name, &sym->declared_at); - - return; - } - sym->assoc->variable = to_var; + sym->assoc->variable = (target->expr_type == EXPR_VARIABLE + && !gfc_has_vector_subscript (target)); /* Finally resolve if this is an array or not. */ if (sym->attr.dimension && target->rank == 0) @@ -7617,7 +7613,7 @@ resolve_assoc_var (gfc_symbol* sym, bool resolve_target) /* Resolve a SELECT TYPE statement. */ static void -resolve_select_type (gfc_code *code) +resolve_select_type (gfc_code *code, gfc_namespace *old_ns) { gfc_symbol *selector_type; gfc_code *body, *new_st, *if_st, *tail; @@ -7686,8 +7682,8 @@ resolve_select_type (gfc_code *code) error++; continue; } - else - default_case = body; + + default_case = body; } } @@ -7895,8 +7891,13 @@ resolve_select_type (gfc_code *code) default_case->next = if_st; } - resolve_select (code); + /* Resolve the internal code. This can not be done earlier because + it requires that the sym->assoc of selectors is set already. */ + gfc_current_ns = ns; + gfc_resolve_blocks (code->block, gfc_current_ns); + gfc_current_ns = old_ns; + resolve_select (code); } @@ -7924,6 +7925,13 @@ resolve_transfer (gfc_code *code) && exp->expr_type != EXPR_FUNCTION)) return; + /* If we are reading, the variable will be changed. Note that + code->ext.dt may be NULL if the TRANSFER is related to + an INQUIRE statement -- but in this case, we are not reading, either. */ + if (code->ext.dt && code->ext.dt->dt_io_kind->value.iokind == M_READ + && gfc_check_vardef_context (exp, false, _("item in READ")) == FAILURE) + return; + sym = exp->symtree->n.sym; ts = &sym->ts; @@ -8657,7 +8665,6 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns) } } - if (lhs->ts.type == BT_CHARACTER && gfc_option.warn_character_truncation) { @@ -8698,15 +8705,6 @@ resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns) if (gfc_pure (NULL)) { - if (gfc_impure_variable (lhs->symtree->n.sym)) - { - gfc_error ("Cannot assign to variable '%s' in PURE " - "procedure at %L", - lhs->symtree->n.sym->name, - &lhs->where); - return rval; - } - if (lhs->ts.type == BT_DERIVED && lhs->expr_type == EXPR_VARIABLE && lhs->ts.u.derived->attr.pointer_comp @@ -8810,9 +8808,8 @@ resolve_code (gfc_code *code, gfc_namespace *ns) gfc_resolve_omp_do_blocks (code, ns); break; case EXEC_SELECT_TYPE: - gfc_current_ns = code->ext.block.ns; - gfc_resolve_blocks (code->block, gfc_current_ns); - gfc_current_ns = ns; + /* Blocks are handled in resolve_select_type because we have + to transform the SELECT TYPE into ASSOCIATE first. */ break; case EXEC_OMP_WORKSHARE: omp_workshare_save = omp_workshare_flag; @@ -8899,6 +8896,10 @@ resolve_code (gfc_code *code, gfc_namespace *ns) if (t == FAILURE) break; + if (gfc_check_vardef_context (code->expr1, false, _("assignment")) + == FAILURE) + break; + if (resolve_ordinary_assign (code, ns)) { if (code->op == EXEC_COMPCALL) @@ -8923,11 +8924,27 @@ resolve_code (gfc_code *code, gfc_namespace *ns) break; case EXEC_POINTER_ASSIGN: - if (t == FAILURE) - break; + { + gfc_expr* e; - gfc_check_pointer_assign (code->expr1, code->expr2); - break; + if (t == FAILURE) + break; + + /* This is both a variable definition and pointer assignment + context, so check both of them. For rank remapping, a final + array ref may be present on the LHS and fool gfc_expr_attr + used in gfc_check_vardef_context. Remove it. */ + e = remove_last_array_ref (code->expr1); + t = gfc_check_vardef_context (e, true, _("pointer assignment")); + if (t == SUCCESS) + t = gfc_check_vardef_context (e, false, _("pointer assignment")); + gfc_free_expr (e); + if (t == FAILURE) + break; + + gfc_check_pointer_assign (code->expr1, code->expr2); + break; + } case EXEC_ARITHMETIC_IF: if (t == SUCCESS @@ -8970,7 +8987,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns) break; case EXEC_SELECT_TYPE: - resolve_select_type (code); + resolve_select_type (code, ns); break; case EXEC_BLOCK: diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index a7b678f406a..8748ecfba8b 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see #include "intrinsic.h" #include "target-memory.h" #include "constructor.h" +#include "version.h" /* For version_string. */ gfc_expr gfc_bad_expr; @@ -235,7 +236,8 @@ is_constant_array_expr (gfc_expr *e) for (c = gfc_constructor_first (e->value.constructor); c; c = gfc_constructor_next (c)) - if (c->expr->expr_type != EXPR_CONSTANT) + if (c->expr->expr_type != EXPR_CONSTANT + && c->expr->expr_type != EXPR_STRUCTURE) return false; return true; @@ -4550,6 +4552,8 @@ gfc_simplify_pack (gfc_expr *array, gfc_expr *mask, gfc_expr *vector) return NULL; result = gfc_get_array_expr (array->ts.type, array->ts.kind, &array->where); + if (array->ts.type == BT_DERIVED) + result->ts.u.derived = array->ts.u.derived; array_ctor = gfc_constructor_first (array->value.constructor); vector_ctor = vector @@ -4982,6 +4986,8 @@ gfc_simplify_reshape (gfc_expr *source, gfc_expr *shape_exp, result = gfc_get_array_expr (source->ts.type, source->ts.kind, &source->where); + if (source->ts.type == BT_DERIVED) + result->ts.u.derived = source->ts.u.derived; result->rank = rank; result->shape = gfc_get_shape (rank); for (i = 0; i < rank; i++) @@ -5732,6 +5738,8 @@ gfc_simplify_spread (gfc_expr *source, gfc_expr *dim_expr, gfc_expr *ncopies_exp result = gfc_get_array_expr (source->ts.type, source->ts.kind, &source->where); + if (source->ts.type == BT_DERIVED) + result->ts.u.derived = source->ts.u.derived; result->rank = 1; result->shape = gfc_get_shape (result->rank); mpz_init_set_si (result->shape[0], ncopies); @@ -5750,6 +5758,8 @@ gfc_simplify_spread (gfc_expr *source, gfc_expr *dim_expr, gfc_expr *ncopies_exp result = gfc_get_array_expr (source->ts.type, source->ts.kind, &source->where); + if (source->ts.type == BT_DERIVED) + result->ts.u.derived = source->ts.u.derived; result->rank = source->rank + 1; result->shape = gfc_get_shape (result->rank); @@ -6038,6 +6048,8 @@ gfc_simplify_transpose (gfc_expr *matrix) if (matrix->ts.type == BT_CHARACTER) result->ts.u.cl = matrix->ts.u.cl; + else if (matrix->ts.type == BT_DERIVED) + result->ts.u.derived = matrix->ts.u.derived; matrix_rows = mpz_get_si (matrix->shape[0]); matrix_cols = mpz_get_si (matrix->shape[1]); @@ -6341,6 +6353,8 @@ gfc_simplify_unpack (gfc_expr *vector, gfc_expr *mask, gfc_expr *field) result = gfc_get_array_expr (vector->ts.type, vector->ts.kind, &vector->where); + if (vector->ts.type == BT_DERIVED) + result->ts.u.derived = vector->ts.u.derived; result->rank = mask->rank; result->shape = gfc_copy_shape (mask->shape, mask->rank); @@ -6720,3 +6734,21 @@ gfc_convert_char_constant (gfc_expr *e, bt type ATTRIBUTE_UNUSED, int kind) else return NULL; } + + +gfc_expr * +gfc_simplify_compiler_options (void) +{ + /* FIXME: PR40569 - return the proper compiler arguments. */ + return gfc_get_character_expr (gfc_default_character_kind, + &gfc_current_locus, "", 0); +} + + +gfc_expr * +gfc_simplify_compiler_version (void) +{ + return gfc_get_character_expr (gfc_default_character_kind, + &gfc_current_locus, version_string, + strlen (version_string)); +} diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index b4fc82c6ac9..cd07b63caca 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -4280,6 +4280,13 @@ std_for_isocbinding_symbol (int id) return d; #include "iso-c-binding.def" #undef NAMED_INTCST + +#define NAMED_FUNCTION(a,b,c,d) \ + case a:\ + return d; +#include "iso-c-binding.def" +#undef NAMED_FUNCTION + default: return GFC_STD_F2003; } diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 7bce2ef866b..b32c3eccd8f 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -5136,7 +5136,6 @@ get_array_charlen (gfc_expr *expr, gfc_se *se) } - /* Convert an array for passing as an actual argument. Expressions and vector subscripts are evaluated and stored in a temporary, which is then passed. For whole arrays the descriptor is passed. For array sections @@ -5158,13 +5157,18 @@ get_array_charlen (gfc_expr *expr, gfc_se *se) EXPR is the right-hand side of a pointer assignment and se->expr is the descriptor for the previously-evaluated left-hand side. The function creates an assignment from - EXPR to se->expr. */ + EXPR to se->expr. + + + The se->force_tmp flag disables the non-copying descriptor optimization + that is used for transpose. It may be used in cases where there is an + alias between the transpose argument and another argument in the same + function call. */ void gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) { gfc_loopinfo loop; - gfc_ss *secss; gfc_ss_info *info; int need_tmp; int n; @@ -5175,7 +5179,9 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) tree offset; int full; bool subref_array_target = false; + gfc_expr *arg; + gcc_assert (ss != NULL); gcc_assert (ss != gfc_ss_terminator); /* Special case things we know we can pass easily. */ @@ -5185,22 +5191,21 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) /* If we have a linear array section, we can pass it directly. Otherwise we need to copy it into a temporary. */ - /* Find the SS for the array section. */ - secss = ss; - while (secss != gfc_ss_terminator && secss->type != GFC_SS_SECTION) - secss = secss->next; - - gcc_assert (secss != gfc_ss_terminator); - info = &secss->data.info; + gcc_assert (ss->type == GFC_SS_SECTION); + gcc_assert (ss->expr == expr); + info = &ss->data.info; /* Get the descriptor for the array. */ - gfc_conv_ss_descriptor (&se->pre, secss, 0); + gfc_conv_ss_descriptor (&se->pre, ss, 0); desc = info->descriptor; subref_array_target = se->direct_byref && is_subref_array (expr); need_tmp = gfc_ref_needs_temporary_p (expr->ref) && !subref_array_target; + if (se->force_tmp) + need_tmp = 1; + if (need_tmp) full = 0; else if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc))) @@ -5216,6 +5221,14 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) full = gfc_full_array_ref_p (info->ref, NULL); if (full) + for (n = 0; n < info->dimen; n++) + if (info->dim[n] != n) + { + full = 0; + break; + } + + if (full) { if (se->direct_byref && !se->byref_noassign) { @@ -5245,30 +5258,49 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) break; case EXPR_FUNCTION: + + /* We don't need to copy data in some cases. */ + arg = gfc_get_noncopying_intrinsic_argument (expr); + if (arg) + { + /* This is a call to transpose... */ + gcc_assert (expr->value.function.isym->id == GFC_ISYM_TRANSPOSE); + /* ... which has already been handled by the scalarizer, so + that we just need to get its argument's descriptor. */ + gfc_conv_expr_descriptor (se, expr->value.function.actual->expr, ss); + return; + } + /* A transformational function return value will be a temporary array descriptor. We still need to go through the scalarizer to create the descriptor. Elemental functions ar handled as arbitrary expressions, i.e. copy to a temporary. */ - secss = ss; - /* Look for the SS for this function. */ - while (secss != gfc_ss_terminator - && (secss->type != GFC_SS_FUNCTION || secss->expr != expr)) - secss = secss->next; if (se->direct_byref) { - gcc_assert (secss != gfc_ss_terminator); + gcc_assert (ss->type == GFC_SS_FUNCTION && ss->expr == expr); /* For pointer assignments pass the descriptor directly. */ - se->ss = secss; + if (se->ss == NULL) + se->ss = ss; + else + gcc_assert (se->ss == ss); se->expr = gfc_build_addr_expr (NULL_TREE, se->expr); gfc_conv_expr (se, expr); return; } - if (secss == gfc_ss_terminator) + if (ss->expr != expr || ss->type != GFC_SS_FUNCTION) { - /* Elemental function. */ + if (ss->expr != expr) + /* Elemental function. */ + gcc_assert ((expr->value.function.esym != NULL + && expr->value.function.esym->attr.elemental) + || (expr->value.function.isym != NULL + && expr->value.function.isym->elemental)); + else + gcc_assert (ss->type == GFC_SS_INTRINSIC); + need_tmp = 1; if (expr->ts.type == BT_CHARACTER && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT) @@ -5279,7 +5311,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) else { /* Transformational function. */ - info = &secss->data.info; + info = &ss->data.info; need_tmp = 0; } break; @@ -5292,12 +5324,10 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) { need_tmp = 0; info = &ss->data.info; - secss = ss; } else { need_tmp = 1; - secss = NULL; info = NULL; } break; @@ -5305,11 +5335,15 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) default: /* Something complicated. Copy it into a temporary. */ need_tmp = 1; - secss = NULL; info = NULL; break; } + /* If we are creating a temporary, we don't need to bother about aliases + anymore. */ + if (need_tmp) + se->force_tmp = 0; + gfc_init_loopinfo (&loop); /* Associate the SS with the loop. */ @@ -5421,7 +5455,6 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) se->string_length = gfc_get_expr_charlen (expr); desc = info->descriptor; - gcc_assert (secss && secss != gfc_ss_terminator); if (se->direct_byref && !se->byref_noassign) { /* For pointer assignments we fill in the destination. */ @@ -5439,12 +5472,11 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) } offset = gfc_index_zero_node; - dim = 0; /* The following can be somewhat confusing. We have two descriptors, a new one and the original array. {parm, parmtype, dim} refer to the new one. - {desc, type, n, secss, loop} refer to the original, which maybe + {desc, type, n, loop} refer to the original, which maybe a descriptorless array. The bounds of the scalarization are the bounds of the section. We don't have to worry about numeric overflows when calculating @@ -5479,9 +5511,6 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) } else { - /* Check we haven't somehow got out of sync. */ - gcc_assert (info->dim[dim] == n); - /* Evaluate and remember the start of the section. */ start = info->start[n]; stride = gfc_evaluate_now (stride, &loop.pre); @@ -5505,6 +5534,14 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) /* Vector subscripts need copying and are handled elsewhere. */ if (info->ref) gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_RANGE); + + /* look for the corresponding scalarizer dimension: dim. */ + for (dim = 0; dim < ndim; dim++) + if (info->dim[dim] == n) + break; + + /* loop exited early: the DIM being looked for has been found. */ + gcc_assert (dim < ndim); /* Set the new lower bound. */ from = loop.from[dim]; @@ -5559,8 +5596,6 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss) /* Store the new stride. */ gfc_conv_descriptor_stride_set (&loop.pre, parm, gfc_rank_cst[dim], stride); - - dim++; } if (se->data_not_needed) diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 0ff297f7e6b..d15d673af03 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -1044,6 +1044,7 @@ gfc_get_symbol_decl (gfc_symbol * sym) tree length = NULL_TREE; tree attributes; int byref; + bool intrinsic_array_parameter = false; gcc_assert (sym->attr.referenced || sym->attr.use_assoc @@ -1181,6 +1182,12 @@ gfc_get_symbol_decl (gfc_symbol * sym) if (sym->attr.intrinsic) internal_error ("intrinsic variable which isn't a procedure"); + /* Special case for array-valued named constants from intrinsic + procedures; those are inlined. */ + if (sym->attr.use_assoc && sym->from_intmod && sym->attr.dimension + && sym->attr.flavor == FL_PARAMETER) + intrinsic_array_parameter = true; + /* Create string length decl first so that they can be used in the type declaration. */ if (sym->ts.type == BT_CHARACTER) @@ -1200,7 +1207,7 @@ gfc_get_symbol_decl (gfc_symbol * sym) if (sym->module) { gfc_set_decl_assembler_name (decl, gfc_sym_mangled_identifier (sym)); - if (sym->attr.use_assoc) + if (sym->attr.use_assoc && !intrinsic_array_parameter) DECL_IGNORED_P (decl) = 1; } @@ -1226,7 +1233,7 @@ gfc_get_symbol_decl (gfc_symbol * sym) && !sym->attr.data && !sym->attr.allocatable && (sym->value && !sym->ns->proc_name->attr.is_main_program) - && !sym->attr.use_assoc)) + && !(sym->attr.use_assoc && !intrinsic_array_parameter))) gfc_defer_symbol_init (sym); gfc_finish_var_decl (decl, sym); @@ -1280,7 +1287,14 @@ gfc_get_symbol_decl (gfc_symbol * sym) if (sym->attr.assign) gfc_add_assign_aux_vars (sym); - if (TREE_STATIC (decl) && !sym->attr.use_assoc + if (intrinsic_array_parameter) + { + TREE_STATIC (decl) = 1; + DECL_EXTERNAL (decl) = 0; + } + + if (TREE_STATIC (decl) + && !(sym->attr.use_assoc && !intrinsic_array_parameter) && (sym->attr.save || sym->ns->proc_name->attr.is_main_program || gfc_option.flag_max_stack_var_size == 0 || sym->attr.data || sym->ns->proc_name->attr.flavor == FL_MODULE)) diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 8d4295fce8f..a6837c95e90 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -2770,7 +2770,7 @@ conv_isocbinding_procedure (gfc_se * se, gfc_symbol * sym, int gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, - gfc_actual_arglist * arg, gfc_expr * expr, + gfc_actual_arglist * args, gfc_expr * expr, VEC(tree,gc) *append_args) { gfc_interface_mapping mapping; @@ -2789,6 +2789,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, VEC(tree,gc) *stringargs; tree result = NULL; gfc_formal_arglist *formal; + gfc_actual_arglist *arg; int has_alternate_specifier = 0; bool need_interface_mapping; bool callee_alloc; @@ -2809,7 +2810,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, gfc_clear_ts (&ts); if (sym->from_intmod == INTMOD_ISO_C_BINDING - && conv_isocbinding_procedure (se, sym, arg)) + && conv_isocbinding_procedure (se, sym, args)) return 0; gfc_is_proc_ptr_comp (expr, &comp); @@ -2859,7 +2860,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, } /* Evaluate the arguments. */ - for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL) + for (arg = args; arg != NULL; + arg = arg->next, formal = formal ? formal->next : NULL) { e = arg->expr; fsym = formal ? formal->sym : NULL; @@ -3040,6 +3042,24 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, else f = f || !sym->attr.always_explicit; + /* If the argument is a function call that may not create + a temporary for the result, we have to check that we + can do it, i.e. that there is no alias between this + argument and another one. */ + if (gfc_get_noncopying_intrinsic_argument (e) != NULL) + { + sym_intent intent; + + if (fsym != NULL) + intent = fsym->attr.intent; + else + intent = INTENT_UNKNOWN; + + if (gfc_check_fncall_dependency (e, intent, sym, args, + NOT_ELEMENTAL)) + parmse.force_tmp = 1; + } + if (e->expr_type == EXPR_VARIABLE && is_subref_array (e)) /* The actual argument is a component reference to an @@ -3169,27 +3189,16 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, if (gfc_option.rtcheck & GFC_RTCHECK_POINTER && e != NULL) { - symbol_attribute *attr; + symbol_attribute attr; char *msg; tree cond; - if (e->expr_type == EXPR_VARIABLE) - attr = &e->symtree->n.sym->attr; - else if (e->expr_type == EXPR_FUNCTION) - { - /* For intrinsic functions, the gfc_attr are not available. */ - if (e->symtree->n.sym->attr.generic && e->value.function.isym) - goto end_pointer_check; - - if (e->symtree->n.sym->attr.generic) - attr = &e->value.function.esym->attr; - else - attr = &e->symtree->n.sym->result->attr; - } + if (e->expr_type == EXPR_VARIABLE || e->expr_type == EXPR_FUNCTION) + attr = gfc_expr_attr (e); else goto end_pointer_check; - if (attr->optional) + if (attr.optional) { /* If the actual argument is an optional pointer/allocatable and the formal argument takes an nonpointer optional value, @@ -3198,16 +3207,16 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, See Fortran 2003, Section 12.4.1.6 item (7)+(8). */ tree present, null_ptr, type; - if (attr->allocatable + if (attr.allocatable && (fsym == NULL || !fsym->attr.allocatable)) asprintf (&msg, "Allocatable actual argument '%s' is not " "allocated or not present", e->symtree->n.sym->name); - else if (attr->pointer + else if (attr.pointer && (fsym == NULL || !fsym->attr.pointer)) asprintf (&msg, "Pointer actual argument '%s' is not " "associated or not present", e->symtree->n.sym->name); - else if (attr->proc_pointer + else if (attr.proc_pointer && (fsym == NULL || !fsym->attr.proc_pointer)) asprintf (&msg, "Proc-pointer actual argument '%s' is not " "associated or not present", @@ -3231,15 +3240,15 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, } else { - if (attr->allocatable + if (attr.allocatable && (fsym == NULL || !fsym->attr.allocatable)) asprintf (&msg, "Allocatable actual argument '%s' is not " "allocated", e->symtree->n.sym->name); - else if (attr->pointer + else if (attr.pointer && (fsym == NULL || !fsym->attr.pointer)) asprintf (&msg, "Pointer actual argument '%s' is not " "associated", e->symtree->n.sym->name); - else if (attr->proc_pointer + else if (attr.proc_pointer && (fsym == NULL || !fsym->attr.proc_pointer)) asprintf (&msg, "Proc-pointer actual argument '%s' is not " "associated", e->symtree->n.sym->name); diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index 7933a941d94..ebea9af69cc 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -333,6 +333,11 @@ void init_c_interop_kinds (void) c_interop_kinds_table[a].f90_type = BT_PROCEDURE; \ c_interop_kinds_table[a].value = 0; #include "iso-c-binding.def" +#define NAMED_FUNCTION(a,b,c,d) \ + strncpy (c_interop_kinds_table[a].name, b, strlen(b) + 1); \ + c_interop_kinds_table[a].f90_type = BT_PROCEDURE; \ + c_interop_kinds_table[a].value = c; +#include "iso-c-binding.def" } diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index acdd3e30995..a883cf5582d 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -81,6 +81,11 @@ typedef struct gfc_se /* If set, gfc_conv_procedure_call does not put byref calls into se->pre. */ unsigned no_function_call:1; + /* If set, we will force the creation of a temporary. Useful to disable + non-copying procedure argument passing optimizations, when some function + args alias. */ + unsigned force_tmp:1; + /* Scalarization parameters. */ struct gfc_se *parent; struct gfc_ss *ss; diff --git a/gcc/function.c b/gcc/function.c index fac8b75f3d9..a11f248dc35 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -1405,6 +1405,11 @@ instantiate_new_reg (rtx x, HOST_WIDE_INT *poffset) #endif offset = cfa_offset; } + else if (x == virtual_preferred_stack_boundary_rtx) + { + new_rtx = GEN_INT (crtl->preferred_stack_boundary / BITS_PER_UNIT); + offset = 0; + } else return NULL_RTX; diff --git a/gcc/gcc.c b/gcc/gcc.c index 479d7daf2ff..2614faf5b7b 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -30,44 +30,6 @@ CC recognizes how to compile each input file by suffixes in the file names. Once it knows which kind of compilation to perform, the procedure for compilation is specified by a string called a "spec". */ -/* A Short Introduction to Adding a Command-Line Option. - - Before adding a command-line option, consider if it is really - necessary. Each additional command-line option adds complexity and - is difficult to remove in subsequent versions. - - In the following, consider adding the command-line argument - `--bar'. - - 1. Each command-line option is specified in the specs file. The - notation is described below in the comment entitled "The Specs - Language". Read it. - - 2. In this file, add an entry to "option_map" equating the long - `--' argument version and any shorter, single letter version. Read - the comments in the declaration of "struct option_map" for an - explanation. Do not omit the first `-'. - - 3. Look in the "specs" file to determine which program or option - list should be given the argument, e.g., "cc1_options". Add the - appropriate syntax for the shorter option version to the - corresponding "const char *" entry in this file. Omit the first - `-' from the option. For example, use `-bar', rather than `--bar'. - - 4. If the argument takes an argument, e.g., `--baz argument1', - modify either DEFAULT_SWITCH_TAKES_ARG or - DEFAULT_WORD_SWITCH_TAKES_ARG in gcc.h. Omit the first `-' - from `--baz'. - - 5. Document the option in this file's display_help(). If the - option is passed to a subprogram, modify its corresponding - function, e.g., cppinit.c:print_help() or toplev.c:display_help(), - instead. - - 6. Compile and test. Make sure that your new specs file is being - read. For example, use a debugger to investigate the value of - "specs_file" in main(). */ - #include "config.h" #include "system.h" #include "coretypes.h" @@ -263,7 +225,6 @@ static void add_prefix (struct path_prefix *, const char *, const char *, int, int, int); static void add_sysrooted_prefix (struct path_prefix *, const char *, const char *, int, int, int); -static void translate_options (int *, const char *const **); static char *skip_whitespace (char *); static void delete_if_ordinary (const char *); static void delete_temp_files (void); @@ -300,7 +261,7 @@ static void display_help (void); static void add_preprocessor_option (const char *, int); static void add_assembler_option (const char *, int); static void add_linker_option (const char *, int); -static void process_command (int, const char **); +static void process_command (unsigned int, struct cl_decoded_option *); static int execute (void); static void alloc_args (void); static void clear_args (void); @@ -802,9 +763,10 @@ static const char *cc1_options = %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}} \ %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\ %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\ - %{Qn:-fno-ident} %{--help:--help}\ - %{--target-help:--target-help}\ - %{--help=*:--help=%(VALUE)}\ + %{Qn:-fno-ident} %{-help:--help}\ + %{-target-help:--target-help}\ + %{-version:--version}\ + %{-help=*:--help=%*}\ %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\ %{fsyntax-only:-o %j} %{-param*}\ %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\ @@ -959,7 +921,7 @@ static const struct compiler default_compilers[] = {".java", "#Java", 0, 0, 0}, {".class", "#Java", 0, 0, 0}, {".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0}, /* Next come the entries for C. */ - {".c", "@c", 0, 1, 1}, + {".c", "@c", 0, 0, 1}, {"@c", /* cc1 has an integrated ISO C preprocessor. We should invoke the external preprocessor if -save-temps is given. */ @@ -967,20 +929,13 @@ static const struct compiler default_compilers[] = %{!E:%{!M:%{!MM:\ %{traditional|ftraditional:\ %eGNU C no longer supports -traditional without -E}\ - %{!combine:\ - %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ - %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\ - cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \ - %(cc1_options)}\ - %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\ - cc1 %(cpp_unique_options) %(cc1_options)}}}\ - %{!fsyntax-only:%(invoke_as)}} \ - %{combine:\ - %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ - %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i}}\ - %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\ - cc1 %(cpp_unique_options) %(cc1_options)}}\ - %{!fsyntax-only:%(invoke_as)}}}}}}", 0, 1, 1}, + %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \ + %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\ + cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \ + %(cc1_options)}\ + %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\ + cc1 %(cpp_unique_options) %(cc1_options)}}}\ + %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 1}, {"-", "%{!E:%e-E or -x required when input is from standard input}\ %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0, 0, 0}, @@ -1000,7 +955,7 @@ static const struct compiler default_compilers[] = cc1 %(cpp_unique_options) %(cc1_options)\ %{!fdump-ada-spec*:-o %g.s %{!o*:--output-pch=%i.gch}\ %W{o*:--output-pch=%*}}%V}}}}}}", 0, 0, 0}, - {".i", "@cpp-output", 0, 1, 0}, + {".i", "@cpp-output", 0, 0, 0}, {"@cpp-output", "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 1, 0}, {".s", "@assembler", 0, 1, 0}, @@ -1049,342 +1004,6 @@ static char **assembler_options; static int n_preprocessor_options; static char **preprocessor_options; -/* Define how to map long options into short ones. */ - -/* This structure describes one mapping. */ -struct option_map -{ - /* The long option's name. */ - const char *const name; - /* The equivalent short option. */ - const char *const equivalent; - /* Argument info. A string of flag chars; NULL equals no options. - a => argument required. - o => argument optional. - j => join argument to equivalent, making one word. - * => require other text after NAME as an argument. */ - const char *const arg_info; -}; - -/* This is the table of mappings. Mappings are tried sequentially - for each option encountered; the first one that matches, wins. */ - -static const struct option_map option_map[] = - { - {"--all-warnings", "-Wall", 0}, - {"--ansi", "-ansi", 0}, - {"--assemble", "-S", 0}, - {"--assert", "-A", "a"}, - {"--classpath", "-fclasspath=", "aj"}, - {"--bootclasspath", "-fbootclasspath=", "aj"}, - {"--CLASSPATH", "-fclasspath=", "aj"}, - {"--combine", "-combine", 0}, - {"--comments", "-C", 0}, - {"--comments-in-macros", "-CC", 0}, - {"--compile", "-c", 0}, - {"--debug", "-g", "oj"}, - {"--define-macro", "-D", "aj"}, - {"--dependencies", "-M", 0}, - {"--dump", "-d", "aj"}, - {"--dumpbase", "-dumpbase", "a"}, - {"--dumpdir", "-dumpdir", "a"}, - {"--encoding", "-fencoding=", "aj"}, - {"--entry", "-e", 0}, - {"--extra-warnings", "-W", 0}, - {"--extdirs", "-fextdirs=", "aj"}, - {"--for-assembler", "-Wa", "a"}, - {"--for-linker", "-Xlinker", "a"}, - {"--force-link", "-u", "a"}, - {"--coverage", "-coverage", 0}, - {"--imacros", "-imacros", "a"}, - {"--include", "-include", "a"}, - {"--include-barrier", "-I-", 0}, - {"--include-directory", "-I", "aj"}, - {"--include-directory-after", "-idirafter", "a"}, - {"--include-prefix", "-iprefix", "a"}, - {"--include-with-prefix", "-iwithprefix", "a"}, - {"--include-with-prefix-before", "-iwithprefixbefore", "a"}, - {"--include-with-prefix-after", "-iwithprefix", "a"}, - {"--language", "-x", "a"}, - {"--library-directory", "-L", "a"}, - {"--machine", "-m", "aj"}, - {"--machine-", "-m", "*j"}, - {"--no-canonical-prefixes", "-no-canonical-prefixes", 0}, - {"--no-integrated-cpp", "-no-integrated-cpp", 0}, - {"--no-line-commands", "-P", 0}, - {"--no-precompiled-includes", "-noprecomp", 0}, - {"--no-standard-includes", "-nostdinc", 0}, - {"--no-standard-libraries", "-nostdlib", 0}, - {"--no-warnings", "-w", 0}, - {"--optimize", "-O", "oj"}, - {"--output", "-o", "a"}, - {"--output-class-directory", "-foutput-class-dir=", "ja"}, - {"--param", "--param", "a"}, - {"--pass-exit-codes", "-pass-exit-codes", 0}, - {"--pedantic", "-pedantic", 0}, - {"--pedantic-errors", "-pedantic-errors", 0}, - {"--pie", "-pie", 0}, - {"--pipe", "-pipe", 0}, - {"--prefix", "-B", "a"}, - {"--preprocess", "-E", 0}, - {"--print-search-dirs", "-print-search-dirs", 0}, - {"--print-file-name", "-print-file-name=", "aj"}, - {"--print-libgcc-file-name", "-print-libgcc-file-name", 0}, - {"--print-missing-file-dependencies", "-MG", 0}, - {"--print-multi-lib", "-print-multi-lib", 0}, - {"--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}, - {"--resource", "-fcompile-resource=", "aj"}, - {"--save-temps", "-save-temps", 0}, - {"--shared", "-shared", 0}, - {"--specs", "-specs=", "aj"}, - {"--static", "-static", 0}, - {"--std", "-std=", "aj"}, - {"--symbolic", "-symbolic", 0}, - {"--sysroot", "--sysroot=", "aj"}, - {"--time", "-time", 0}, - {"--trace-includes", "-H", 0}, - {"--traditional", "-traditional", 0}, - {"--traditional-cpp", "-traditional-cpp", 0}, - {"--trigraphs", "-trigraphs", 0}, - {"--undefine-macro", "-U", "aj"}, - {"--user-dependencies", "-MM", 0}, - {"--verbose", "-v", 0}, - {"--warn-", "-W", "*j"}, - {"--write-dependencies", "-MD", 0}, - {"--write-user-dependencies", "-MMD", 0}, - {"--", "-f", "*j"} - }; - - -#ifdef TARGET_OPTION_TRANSLATE_TABLE -static const struct { - const char *const option_found; - const char *const replacements; -} target_option_translations[] = -{ - TARGET_OPTION_TRANSLATE_TABLE, - { 0, 0 } -}; -#endif - -/* Translate the options described by *ARGCP and *ARGVP. - Make a new vector and store it back in *ARGVP, - and store its length in *ARGCP. */ - -static void -translate_options (int *argcp, const char *const **argvp) -{ - int i; - int argc = *argcp; - const char *const *argv = *argvp; - int newvsize = (argc + 2) * 2 * sizeof (const char *); - const char **newv = XNEWVAR (const char *, newvsize); - int newindex = 0; - - i = 0; - newv[newindex++] = argv[i++]; - - while (i < argc) - { -#ifdef TARGET_OPTION_TRANSLATE_TABLE - int tott_idx; - - for (tott_idx = 0; - target_option_translations[tott_idx].option_found; - tott_idx++) - { - if (strcmp (target_option_translations[tott_idx].option_found, - argv[i]) == 0) - { - int spaces = 1; - const char *sp; - char *np; - - for (sp = target_option_translations[tott_idx].replacements; - *sp; sp++) - { - if (*sp == ' ') - spaces ++; - } - - newvsize += spaces * sizeof (const char *); - newv = XRESIZEVAR (const char *, newv, newvsize); - - sp = target_option_translations[tott_idx].replacements; - np = xstrdup (sp); - - while (1) - { - while (*np == ' ') - np++; - if (*np == 0) - break; - newv[newindex++] = np; - while (*np != ' ' && *np) - np++; - if (*np == 0) - break; - *np++ = 0; - } - - i ++; - break; - } - } - if (target_option_translations[tott_idx].option_found) - continue; -#endif - - /* Translate -- options. */ - if (argv[i][0] == '-' && argv[i][1] == '-') - { - size_t j; - /* Find a mapping that applies to this option. */ - for (j = 0; j < ARRAY_SIZE (option_map); j++) - { - size_t optlen = strlen (option_map[j].name); - size_t arglen = strlen (argv[i]); - size_t complen = arglen > optlen ? optlen : arglen; - const char *arginfo = option_map[j].arg_info; - - if (arginfo == 0) - arginfo = ""; - - if (!strncmp (argv[i], option_map[j].name, complen)) - { - const char *arg = 0; - - if (arglen < optlen) - { - size_t k; - for (k = j + 1; k < ARRAY_SIZE (option_map); k++) - if (strlen (option_map[k].name) >= arglen - && !strncmp (argv[i], option_map[k].name, arglen)) - { - error ("ambiguous abbreviation %s", argv[i]); - break; - } - - if (k != ARRAY_SIZE (option_map)) - break; - } - - if (arglen > optlen) - { - /* If the option has an argument, accept that. */ - if (argv[i][optlen] == '=') - arg = argv[i] + optlen + 1; - - /* If this mapping requires extra text at end of name, - accept that as "argument". */ - else if (strchr (arginfo, '*') != 0) - arg = argv[i] + optlen; - - /* Otherwise, extra text at end means mismatch. - Try other mappings. */ - else - continue; - } - - else if (strchr (arginfo, '*') != 0) - { - error ("incomplete %qs option", option_map[j].name); - break; - } - - /* Handle arguments. */ - if (strchr (arginfo, 'a') != 0) - { - if (arg == 0) - { - if (i + 1 == argc) - { - error ("missing argument to %qs option", - option_map[j].name); - break; - } - - arg = argv[++i]; - } - } - else if (strchr (arginfo, '*') != 0) - ; - else if (strchr (arginfo, 'o') == 0) - { - if (arg != 0) - error ("extraneous argument to %qs option", - option_map[j].name); - arg = 0; - } - - /* Store the translation as one argv elt or as two. */ - if (arg != 0 && strchr (arginfo, 'j') != 0) - newv[newindex++] = concat (option_map[j].equivalent, arg, - NULL); - else if (arg != 0) - { - newv[newindex++] = option_map[j].equivalent; - newv[newindex++] = arg; - } - else - newv[newindex++] = option_map[j].equivalent; - - break; - } - } - i++; - } - - /* Handle old-fashioned options--just copy them through, - with their arguments. */ - else if (argv[i][0] == '-') - { - const char *p = argv[i] + 1; - int c = *p; - int nskip = 1; - - if (SWITCH_TAKES_ARG (c) > (p[1] != 0)) - nskip += SWITCH_TAKES_ARG (c) - (p[1] != 0); - else if (WORD_SWITCH_TAKES_ARG (p)) - nskip += WORD_SWITCH_TAKES_ARG (p); - else if ((c == 'B' || c == 'b' || c == 'x') - && p[1] == 0) - nskip += 1; - else if (! strcmp (p, "Xlinker")) - nskip += 1; - else if (! strcmp (p, "Xpreprocessor")) - nskip += 1; - else if (! strcmp (p, "Xassembler")) - nskip += 1; - - /* Watch out for an option at the end of the command line that - is missing arguments, and avoid skipping past the end of the - command line. */ - if (nskip + i > argc) - nskip = argc - i; - - while (nskip > 0) - { - newv[newindex++] = argv[i++]; - nskip--; - } - } - else - /* Ordinary operands. */ - newv[newindex++] = argv[i++]; - } - - newv[newindex] = 0; - - *argvp = newv; - *argcp = newindex; -} - static char * skip_whitespace (char *p) { @@ -3322,7 +2941,6 @@ display_help (void) fputs (_(" -Xassembler <arg> Pass <arg> on to the assembler\n"), stdout); fputs (_(" -Xpreprocessor <arg> Pass <arg> on to the preprocessor\n"), stdout); fputs (_(" -Xlinker <arg> Pass <arg> on to the linker\n"), stdout); - fputs (_(" -combine Pass multiple source files to compiler at once\n"), stdout); fputs (_(" -save-temps Do not delete intermediate files\n"), stdout); fputs (_(" -save-temps=<arg> Do not delete intermediate files\n"), stdout); fputs (_("\ @@ -3555,8 +3173,7 @@ driver_handle_option (const struct cl_decoded_option *decoded, printf ("%s\n", spec_machine); exit (0); - case OPT_fversion: - /* translate_options () has turned --version into -fversion. */ + case OPT__version: print_version = 1; /* CPP driver cannot obtain switch from cc1_options. */ @@ -3566,8 +3183,7 @@ driver_handle_option (const struct cl_decoded_option *decoded, add_linker_option ("--version", strlen ("--version")); break; - case OPT_fhelp: - /* translate_options () has turned --help into -fhelp. */ + case OPT__help: print_help_list = 1; /* CPP driver cannot obtain switch from cc1_options. */ @@ -3577,13 +3193,11 @@ driver_handle_option (const struct cl_decoded_option *decoded, add_linker_option ("--help", 6); break; - case OPT_fhelp_: - /* translate_options () has turned --help into -fhelp. */ + case OPT__help_: print_subprocess_help = 2; break; - case OPT_ftarget_help: - /* translate_options() has turned --target-help into -ftarget-help. */ + case OPT__target_help: print_subprocess_help = 1; /* CPP driver cannot obtain switch from cc1_options. */ @@ -3761,8 +3375,6 @@ driver_handle_option (const struct cl_decoded_option *decoded, case OPT_pipe: validated = true; - /* Fall through. */ - case OPT_combine: /* These options set the variables specified in common.opt automatically, but do need to be saved for spec processing. */ @@ -3894,17 +3506,16 @@ driver_handle_option (const struct cl_decoded_option *decoded, Store its length in `n_switches'. */ static void -process_command (int argc, const char **argv) +process_command (unsigned int decoded_options_count, + struct cl_decoded_option *decoded_options) { - int i; const char *temp; char *temp1; const char *tooldir_prefix; char *(*get_relative_prefix) (const char *, const char *, const char *) = NULL; struct cl_option_handlers handlers; - struct cl_decoded_option *decoded_options; - unsigned int decoded_options_count, j; + unsigned int j; GET_ENVIRONMENT (gcc_exec_prefix, "GCC_EXEC_PREFIX"); @@ -3925,18 +3536,13 @@ process_command (int argc, const char **argv) } } - /* Convert new-style -- options to old-style. */ - translate_options (&argc, - CONST_CAST2 (const char *const **, const char ***, - &argv)); - /* Handle any -no-canonical-prefixes flag early, to assign the function that builds relative prefixes. This function creates default search paths that are needed later in normal option handling. */ - for (i = 1; i < argc; i++) + for (j = 1; j < decoded_options_count; j++) { - if (! strcmp (argv[i], "-no-canonical-prefixes")) + if (decoded_options[j].opt_index == OPT_no_canonical_prefixes) { get_relative_prefix = make_relative_prefix_ignore_links; break; @@ -3946,17 +3552,18 @@ process_command (int argc, const char **argv) get_relative_prefix = make_relative_prefix; /* Set up the default search paths. If there is no GCC_EXEC_PREFIX, - see if we can create it from the pathname specified in argv[0]. */ + see if we can create it from the pathname specified in + decoded_options[0].arg. */ gcc_libexec_prefix = standard_libexec_prefix; #ifndef VMS /* FIXME: make_relative_prefix doesn't yet work for VMS. */ if (!gcc_exec_prefix) { - gcc_exec_prefix = get_relative_prefix (argv[0], + gcc_exec_prefix = get_relative_prefix (decoded_options[0].arg, standard_bindir_prefix, standard_exec_prefix); - gcc_libexec_prefix = get_relative_prefix (argv[0], + gcc_libexec_prefix = get_relative_prefix (decoded_options[0].arg, standard_bindir_prefix, standard_libexec_prefix); if (gcc_exec_prefix) @@ -3983,10 +3590,8 @@ process_command (int argc, const char **argv) #endif /* From this point onward, gcc_exec_prefix is non-null if the toolchain is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX - or an automatically created GCC_EXEC_PREFIX from argv[0]. */ - - decode_cmdline_options_to_array (argc, argv, CL_DRIVER, - &decoded_options, &decoded_options_count); + or an automatically created GCC_EXEC_PREFIX from + decoded_options[0].arg. */ /* Do language-specific adjustment/addition of flags. */ lang_specific_driver (&decoded_options, &decoded_options_count, @@ -4282,7 +3887,7 @@ process_command (int argc, const char **argv) ``make_relative_prefix'' is not compiled for VMS, so don't call it. */ if (target_system_root && !target_system_root_changed && gcc_exec_prefix) { - char *tmp_prefix = get_relative_prefix (argv[0], + char *tmp_prefix = get_relative_prefix (decoded_options[0].arg, standard_bindir_prefix, target_system_root); if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0) @@ -6493,6 +6098,8 @@ main (int argc, char **argv) const char *p; struct user_specs *uptr; char **old_argv = argv; + struct cl_decoded_option *decoded_options; + unsigned int decoded_options_count; /* Initialize here, not in definition. The IRIX 6 O32 cc sometimes chokes on ?: in file-scope variable initializations. */ @@ -6511,7 +6118,10 @@ main (int argc, char **argv) if (argv != old_argv) at_file_supplied = true; - prune_options (&argc, &argv); + decode_cmdline_options_to_array (argc, CONST_CAST2 (const char **, char **, + argv), + CL_DRIVER, + &decoded_options, &decoded_options_count); #ifdef GCC_DRIVER_HOST_INITIALIZATION /* Perform host dependent initialization when needed. */ @@ -6601,7 +6211,7 @@ main (int argc, char **argv) Make a table of specified input files (infiles, n_infiles). Decode switches that are handled locally. */ - process_command (argc, CONST_CAST2 (const char **, char **, argv)); + process_command (decoded_options_count, decoded_options); /* Initialize the vector of specs to just the default. This means one element containing 0s, as a terminator. */ @@ -7003,10 +6613,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" explicit_link_files = XCNEWVEC (char, n_infiles); - if (combine_flag) - combine_inputs = true; - else - combine_inputs = false; + combine_inputs = have_o || flag_wpa; for (i = 0; (int) i < n_infiles; i++) { @@ -7039,63 +6646,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" } if (!combine_inputs && have_c && have_o && lang_n_infiles > 1) - fatal_error ("cannot specify -o with -c, -S or -E with multiple files"); - - if (combine_flag && save_temps_flag) - { - bool save_combine_inputs = combine_inputs; - /* Must do a separate pre-processing pass for C & Objective-C files, to - obtain individual .i files. */ - - combine_inputs = false; - for (i = 0; (int) i < n_infiles; i++) - { - int this_file_error = 0; - - input_file_number = i; - set_input (infiles[i].name); - if (infiles[i].incompiler - && (infiles[i].incompiler)->needs_preprocessing) - input_file_compiler = infiles[i].incompiler; - else - continue; - - if (input_file_compiler) - { - if (input_file_compiler->spec[0] == '#') - { - error ("%s: %s compiler not installed on this system", - gcc_input_filename, &input_file_compiler->spec[1]); - this_file_error = 1; - } - else - { - value = do_spec (input_file_compiler->spec); - infiles[i].preprocessed = true; - if (!have_o_argbuf_index) - fatal_error ("spec %qs is invalid", - input_file_compiler->spec); - infiles[i].name = argbuf[have_o_argbuf_index]; - infiles[i].incompiler - = lookup_compiler (infiles[i].name, - strlen (infiles[i].name), - infiles[i].language); - - if (value < 0) - this_file_error = 1; - } - } - - if (this_file_error) - { - delete_failure_queue (); - errorcount++; - break; - } - clear_failure_queue (); - } - combine_inputs = save_combine_inputs; - } + fatal_error ("cannot specify -o with -c, -S or -E with multiple files"); for (i = 0; (int) i < n_infiles; i++) { @@ -7115,12 +6666,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" /* Figure out which compiler from the file's suffix. */ - if (! combine_inputs) - input_file_compiler - = lookup_compiler (infiles[i].name, input_filename_length, - infiles[i].language); - else - input_file_compiler = infiles[i].incompiler; + input_file_compiler + = lookup_compiler (infiles[i].name, input_filename_length, + infiles[i].language); if (input_file_compiler) { diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c index c6b6e933cc5..3092a43eca0 100644 --- a/gcc/gengtype-parse.c +++ b/gcc/gengtype-parse.c @@ -1,21 +1,21 @@ /* Process source files and output type information. Copyright (C) 2006, 2007 Free Software Foundation, Inc. -This file is part of GCC. + 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 3, or (at your option) any later -version. + 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 3, 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. + 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 COPYING3. If not see -<http://www.gnu.org/licenses/>. */ + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ #include "bconfig.h" #include "system.h" @@ -113,7 +113,7 @@ print_token (int code, const char *value) else if (code < FIRST_TOKEN_WITH_VALUE) return xasprintf ("'%s'", token_names[code - CHAR_TOKEN_OFFSET]); else if (!value) - return token_names[code - CHAR_TOKEN_OFFSET]; /* don't quote these */ + return token_names[code - CHAR_TOKEN_OFFSET]; /* don't quote these */ else return xasprintf (token_value_format[code - FIRST_TOKEN_WITH_VALUE], value); @@ -199,7 +199,7 @@ string_seq (void) l1 = strlen (s1); l2 = strlen (s2); - buf = XRESIZEVEC (char, CONST_CAST(char *, s1), l1 + l2 + 1); + buf = XRESIZEVEC (char, CONST_CAST (char *, s1), l1 + l2 + 1); memcpy (buf + l1, s2, l2 + 1); XDELETE (CONST_CAST (char *, s2)); s1 = buf; @@ -222,7 +222,7 @@ typedef_name (void) require (','); c2 = require (ID); require (')'); - r = concat ("VEC_", c1, "_", c2, (char *)0); + r = concat ("VEC_", c1, "_", c2, (char *) 0); free (CONST_CAST (char *, c1)); free (CONST_CAST (char *, c2)); return r; @@ -239,10 +239,18 @@ consume_balanced (int opener, int closer) for (;;) switch (token ()) { - default: advance (); break; - case '(': consume_balanced ('(',')'); break; - case '[': consume_balanced ('[',']'); break; - case '{': consume_balanced ('{','}'); break; + default: + advance (); + break; + case '(': + consume_balanced ('(', ')'); + break; + case '[': + consume_balanced ('[', ']'); + break; + case '{': + consume_balanced ('{', '}'); + break; case '}': case ']': @@ -250,8 +258,8 @@ consume_balanced (int opener, int closer) if (token () != closer) parse_error ("unbalanced delimiters - expected '%c', have '%c'", closer, token ()); - advance (); - return; + advance (); + return; case EOF_TOKEN: parse_error ("unexpected end of file within %c%c-delimited construct", @@ -272,18 +280,28 @@ consume_until_semi (bool immediate) for (;;) switch (token ()) { - case ';': advance (); return; - default: advance (); break; + case ';': + advance (); + return; + default: + advance (); + break; - case '(': consume_balanced ('(',')'); break; - case '[': consume_balanced ('[',']'); break; - case '{': consume_balanced ('{','}'); break; + case '(': + consume_balanced ('(', ')'); + break; + case '[': + consume_balanced ('[', ']'); + break; + case '{': + consume_balanced ('{', '}'); + break; case '}': case ']': case ')': parse_error ("unmatched '%c' while scanning for ';'", token ()); - return; + return; case EOF_TOKEN: parse_error ("unexpected end of file while scanning for ';'"); @@ -304,28 +322,40 @@ consume_until_comma_or_semi (bool immediate) for (;;) switch (token ()) { - case ',': advance (); return true; - case ';': advance (); return false; - default: advance (); break; + case ',': + advance (); + return true; + case ';': + advance (); + return false; + default: + advance (); + break; - case '(': consume_balanced ('(',')'); break; - case '[': consume_balanced ('[',']'); break; - case '{': consume_balanced ('{','}'); break; + case '(': + consume_balanced ('(', ')'); + break; + case '[': + consume_balanced ('[', ']'); + break; + case '{': + consume_balanced ('{', '}'); + break; case '}': case ']': case ')': parse_error ("unmatched '%s' while scanning for ',' or ';'", print_cur_token ()); - return false; + return false; case EOF_TOKEN: parse_error ("unexpected end of file while scanning for ',' or ';'"); return false; } } - + /* GTY(()) option handling. */ static type_p type (options_p *optsp, bool nested); @@ -401,11 +431,11 @@ nestedptr_optvalue (options_p prev) } /* One GTY(()) option: - ID str_optvalue_opt - | PTR_ALIAS type_optvalue - | PARAM_IS type_optvalue - | NESTED_PTR nestedptr_optvalue - */ + ID str_optvalue_opt + | PTR_ALIAS type_optvalue + | PARAM_IS type_optvalue + | NESTED_PTR nestedptr_optvalue +*/ static options_p option (options_p prev) { @@ -426,8 +456,7 @@ option (options_p prev) return nestedptr_optvalue (prev); default: - parse_error ("expected an option keyword, have %s", - print_cur_token ()); + parse_error ("expected an option keyword, have %s", print_cur_token ()); advance (); return create_option (prev, "", ""); } @@ -479,9 +508,9 @@ gtymarker_opt (void) we don't have to do it. */ /* array_and_function_declarators_opt: - \epsilon - array_and_function_declarators_opt ARRAY - array_and_function_declarators_opt '(' ... ')' + \epsilon + array_and_function_declarators_opt ARRAY + array_and_function_declarators_opt '(' ... ')' where '...' indicates stuff we ignore except insofar as grouping symbols ()[]{} must balance. @@ -510,8 +539,8 @@ array_and_function_declarators_opt (type_p ty) static type_p inner_declarator (type_p, const char **, options_p *); /* direct_declarator: - '(' inner_declarator ')' - gtymarker_opt ID array_and_function_declarators_opt + '(' inner_declarator ')' + gtymarker_opt ID array_and_function_declarators_opt Subroutine of declarator, mutually recursive with inner_declarator; do not use elsewhere. */ @@ -550,7 +579,7 @@ direct_declarator (type_p ty, const char **namep, options_p *optsp) /* The difference between inner_declarator and declarator is in the handling of stars. Consider this declaration: - char * (*pfc) (void) + char * (*pfc) (void) It declares a pointer to a function that takes no arguments and returns a char*. To construct the correct type for this @@ -562,8 +591,8 @@ direct_declarator (type_p ty, const char **namep, options_p *optsp) creating pointers. */ /* inner_declarator: - '*' inner_declarator - direct_declarator + '*' inner_declarator + direct_declarator Mutually recursive subroutine of direct_declarator; do not use elsewhere. */ @@ -609,13 +638,13 @@ declarator (type_p ty, const char **namep, options_p *optsp) /* Structure field(s) declaration: ( - type bitfield ';' - | type declarator bitfield? ( ',' declarator bitfield? )+ ';' + type bitfield ';' + | type declarator bitfield? ( ',' declarator bitfield? )+ ';' )+ Knows that such declarations must end with a close brace (or, erroneously, at EOF). - */ +*/ static pair_p struct_field_seq (void) { @@ -666,7 +695,7 @@ struct_field_seq (void) /* This is called type(), but what it parses (sort of) is what C calls declaration-specifiers and specifier-qualifier-list: - SCALAR + SCALAR | ID // typedef | (STRUCT|UNION) ID? gtymarker? ( '{' gtymarker? struct_field_seq '}' )? | ENUM ID ( '{' ... '}' )? @@ -674,7 +703,7 @@ struct_field_seq (void) Returns a partial type; under some conditions (notably "struct foo GTY((...)) thing;") it may write an options structure to *OPTSP. - */ +*/ static type_p type (options_p *optsp, bool nested) { @@ -695,15 +724,16 @@ type (options_p *optsp, bool nested) case UNION: { options_p opts = 0; - /* GTY annotations follow attribute syntax - GTY_BEFORE_ID is for union/struct declarations - GTY_AFTER_ID is for variable declarations. */ - enum { - NO_GTY, - GTY_BEFORE_ID, - GTY_AFTER_ID - } is_gty = NO_GTY; - bool is_union = (token () == UNION); + /* GTY annotations follow attribute syntax + GTY_BEFORE_ID is for union/struct declarations + GTY_AFTER_ID is for variable declarations. */ + enum + { + NO_GTY, + GTY_BEFORE_ID, + GTY_AFTER_ID + } is_gty = NO_GTY; + bool is_union = (token () == UNION); advance (); /* Top-level structures that are not explicitly tagged GTY(()) @@ -713,8 +743,8 @@ type (options_p *optsp, bool nested) that we can't handle. */ if (nested || token () == GTY_TOKEN) { - is_gty = GTY_BEFORE_ID; - opts = gtymarker_opt (); + is_gty = GTY_BEFORE_ID; + opts = gtymarker_opt (); } if (token () == ID) @@ -722,31 +752,31 @@ type (options_p *optsp, bool nested) else s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line); - /* Unfortunately above GTY_TOKEN check does not capture the - typedef struct_type GTY case. */ + /* Unfortunately above GTY_TOKEN check does not capture the + typedef struct_type GTY case. */ if (token () == GTY_TOKEN) { - is_gty = GTY_AFTER_ID; - opts = gtymarker_opt (); + is_gty = GTY_AFTER_ID; + opts = gtymarker_opt (); } - if (is_gty) - { - if (token () == '{') - { - pair_p fields; - - if (is_gty == GTY_AFTER_ID) - parse_error ("GTY must be specified before identifier"); - - advance (); - fields = struct_field_seq (); - require ('}'); - return new_structure (s, is_union, &lexer_line, fields, opts); - } - } - else if (token () == '{') - consume_balanced ('{', '}'); + if (is_gty) + { + if (token () == '{') + { + pair_p fields; + + if (is_gty == GTY_AFTER_ID) + parse_error ("GTY must be specified before identifier"); + + advance (); + fields = struct_field_seq (); + require ('}'); + return new_structure (s, is_union, &lexer_line, fields, opts); + } + } + else if (token () == '{') + consume_balanced ('{', '}'); if (opts) *optsp = opts; return find_structure (s, is_union); @@ -754,13 +784,13 @@ type (options_p *optsp, bool nested) case ENUM: advance (); - if (token () == ID) - s = advance (); - else - s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line); + if (token () == ID) + s = advance (); + else + s = xasprintf ("anonymous:%s:%d", lexer_line.file, lexer_line.line); if (token () == '{') - consume_balanced ('{','}'); + consume_balanced ('{', '}'); return create_scalar_type (s); default: @@ -821,7 +851,7 @@ struct_or_union (void) } /* GC root declaration: - (extern|static) gtymarker? type ID array_declarators_opt (';'|'=') + (extern|static) gtymarker? type ID array_declarators_opt (';'|'=') If the gtymarker is not present, we ignore the rest of the declaration. */ static void extern_or_static (void) @@ -838,8 +868,8 @@ extern_or_static (void) } opts = gtymarker (); - ty = type (&opts2, true); /* if we get here, it's got a GTY(()) */ - dty = declarator (ty, &name, &dopts); + ty = type (&opts2, true); /* if we get here, it's got a GTY(()) */ + dty = declarator (ty, &name, &dopts); if ((opts && dopts) || (opts && opts2) || (opts2 && dopts)) parse_error ("GTY((...)) specified more than once for %s", name); @@ -864,7 +894,7 @@ extern_or_static (void) static void def_vec (void) { - bool is_scalar = (token() == DEFVEC_I); + bool is_scalar = (token () == DEFVEC_I); const char *type; require2 (DEFVEC_OP, DEFVEC_I); diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 519c9781253..d602bf45cdb 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -21,14 +21,15 @@ #include "bconfig.h" #include "system.h" #include "gengtype.h" -#include "errors.h" /* for fatal */ +#include "errors.h" /* for fatal */ #include "double-int.h" #include "hashtab.h" /* Data types, macros, etc. used only in this file. */ /* Kinds of types we can understand. */ -enum typekind { +enum typekind +{ TYPE_SCALAR, TYPE_STRING, TYPE_STRUCT, @@ -71,16 +72,16 @@ struct pair /* A description of a type. */ enum gc_used_enum - { - GC_UNUSED = 0, - GC_USED, - /* Used for structures whose definitions we haven't seen so far when - we encounter a pointer to it that is annotated with ``maybe_undef''. - If after reading in everything we don't have source file - information for it, we assume that it never has been defined. */ - GC_MAYBE_POINTED_TO, - GC_POINTED_TO - }; +{ + GC_UNUSED = 0, + GC_USED, + /* Used for structures whose definitions we haven't seen so far when + we encounter a pointer to it that is annotated with ``maybe_undef''. + If after reading in everything we don't have source file + information for it, we assume that it never has been defined. */ + GC_MAYBE_POINTED_TO, + GC_POINTED_TO +}; struct type { @@ -88,9 +89,11 @@ struct type type_p next; type_p pointer_to; enum gc_used_enum gc_used; - union { + union + { type_p p; - struct { + struct + { const char *tag; struct fileloc line; pair_p fields; @@ -99,11 +102,13 @@ struct type type_p lang_struct; } s; bool scalar_is_char; - struct { + struct + { type_p p; const char *len; } a; - struct { + struct + { type_p stru; type_p param[NUM_PARAM]; struct fileloc line; @@ -112,13 +117,13 @@ struct type }; #define UNION_P(x) \ - ((x)->kind == TYPE_UNION || \ - ((x)->kind == TYPE_LANG_STRUCT \ - && (x)->u.s.lang_struct->kind == TYPE_UNION)) + ((x)->kind == TYPE_UNION || \ + ((x)->kind == TYPE_LANG_STRUCT \ + && (x)->u.s.lang_struct->kind == TYPE_UNION)) #define UNION_OR_STRUCT_P(x) \ - ((x)->kind == TYPE_UNION \ - || (x)->kind == TYPE_STRUCT \ - || (x)->kind == TYPE_LANG_STRUCT) + ((x)->kind == TYPE_UNION \ + || (x)->kind == TYPE_STRUCT \ + || (x)->kind == TYPE_LANG_STRUCT) /* Structure representing an output file. */ struct outf @@ -129,25 +134,25 @@ struct outf size_t bufused; char *buf; }; -typedef struct outf * outf_p; +typedef struct outf *outf_p; /* An output file, suitable for definitions, that can see declarations made in INPUT_FILE and is linked into every language that uses INPUT_FILE. May return NULL in plugin mode. */ -extern outf_p get_output_file_with_visibility - (const char *input_file); +extern outf_p get_output_file_with_visibility (const char *input_file); const char *get_output_file_name (const char *); /* Print, like fprintf, to O. No-op if O is NULL. */ -static void oprintf (outf_p o, const char *S, ...) - ATTRIBUTE_PRINTF_2; +static void +oprintf (outf_p o, const char *S, ...) + ATTRIBUTE_PRINTF_2; /* The list of output files. */ static outf_p output_files; /* The plugin input files and their number; in that case only a single file is produced. */ -static char** plugin_files; +static char **plugin_files; static size_t nb_plugin_files; /* the generated plugin output name & file */ static outf_p plugin_output; @@ -164,14 +169,14 @@ static size_t srcdir_len = 0; static outf_p create_file (const char *, const char *); -static const char * get_file_basename (const char *); -static const char * get_file_realbasename (const char *); -static const char * get_file_srcdir_relative_path (const char *); +static const char *get_file_basename (const char *); +static const char *get_file_realbasename (const char *); +static const char *get_file_srcdir_relative_path (const char *); static int get_prefix_langdir_index (const char *); -static const char * get_file_langdir (const char *); - +static const char *get_file_langdir (const char *); + /* Nonzero iff an error has occurred. */ bool hit_error = false; @@ -251,13 +256,13 @@ get_lang_bitmap (const char *gtfile) if (gtfile == this_file) /* Things defined in this file are universal. */ - return (((lang_bitmap)1) << num_lang_dirs) - 1; + return (((lang_bitmap) 1) << num_lang_dirs) - 1; else { lang_bitmap n = 0; int i; for (i = -(int) sizeof (lang_bitmap); i < 0; i++) - n = (n << CHAR_BIT) + (unsigned char)gtfile[i]; + n = (n << CHAR_BIT) + (unsigned char) gtfile[i]; return n; } } @@ -270,7 +275,7 @@ set_lang_bitmap (char *gtfile, lang_bitmap n) int i; for (i = -1; i >= -(int) sizeof (lang_bitmap); i--) { - gtfile[i] = n & ((1U << CHAR_BIT)-1); + gtfile[i] = n & ((1U << CHAR_BIT) - 1); n >>= CHAR_BIT; } } @@ -319,8 +324,7 @@ measure_input_list (FILE *list) touch *HEREP, and sets *LINEP to NULL. POS is used for diagnostics. */ static bool -read_input_line (FILE *list, char **herep, char **linep, - struct fileloc *pos) +read_input_line (FILE *list, char **herep, char **linep, struct fileloc *pos) { char *here = *herep; char *line; @@ -349,12 +353,13 @@ read_input_line (FILE *list, char **herep, char **linep, if (c == ']') { - c = getc (list); /* eat what should be a newline */ + c = getc (list); /* eat what should be a newline */ if (c != '\n' && c != EOF) error_at_line (pos, "junk on line after language tag [%s]", line); } else - error_at_line (pos, "missing close bracket for language tag [%s", line); + error_at_line (pos, "missing close bracket for language tag [%s", + line); *herep = here; *linep = line; @@ -429,7 +434,8 @@ read_input_list (const char *listname) for (i = 0; i < langno; i++) if (strcmp (lang_dir_names[i], line) == 0) { - error_at_line (&epos, "duplicate language tag [%s]", line); + error_at_line (&epos, "duplicate language tag [%s]", + line); curlangs = 1 << i; here = committed; goto next_line; @@ -449,13 +455,15 @@ read_input_list (const char *listname) current language to the existing string's bitmap. */ lang_bitmap bmap = get_lang_bitmap (gt_files[i]); if (bmap & curlangs) - error_at_line (&epos, "file %s specified more than once " - "for language %s", line, langno == 0 - ? "(all)" - : lang_dir_names[langno - 1]); + error_at_line (&epos, + "file %s specified more than once " + "for language %s", line, + langno == + 0 ? "(all)" : lang_dir_names[langno - + 1]); bmap |= curlangs; - set_lang_bitmap (CONST_CAST(char *, gt_files[i]), bmap); + set_lang_bitmap (CONST_CAST (char *, gt_files[i]), bmap); here = committed; goto next_line; } @@ -465,7 +473,7 @@ read_input_list (const char *listname) } } /* Update the global counts now that we know accurately how many - things there are. (We do not bother resizing the arrays down.) */ + things there are. (We do not bother resizing the arrays down.) */ num_lang_dirs = langno; /* Add the plugin files if provided. */ if (plugin_files) @@ -493,7 +501,7 @@ read_input_list (const char *listname) { size_t l; for (l = 0; l < num_lang_dirs; l++) - if ((size_t)(slashpos - basename) == strlen (lang_dir_names [l]) + if ((size_t) (slashpos - basename) == strlen (lang_dir_names[l]) && memcmp (basename, lang_dir_names[l], strlen (lang_dir_names[l])) == 0) { @@ -503,7 +511,7 @@ read_input_list (const char *listname) basename, lang_dir_names[l]); break; } - } + } } } @@ -512,9 +520,9 @@ read_input_list (const char *listname) fclose (list); } + - /* The one and only TYPE_STRING. */ static struct type string_type = { @@ -527,6 +535,7 @@ static struct type string_type = { static struct type scalar_nonchar = { TYPE_SCALAR, 0, 0, GC_USED, {0} }; + static struct type scalar_char = { TYPE_SCALAR, 0, 0, GC_USED, {0} }; @@ -538,8 +547,7 @@ static type_p structures; static type_p param_structs; static pair_p variables; -static type_p find_param_structure - (type_p t, type_p param[NUM_PARAM]); +static type_p find_param_structure (type_p t, type_p param[NUM_PARAM]); static type_p adjust_field_tree_exp (type_p t, options_p opt); static type_p adjust_field_rtx_def (type_p t, options_p opt); @@ -597,7 +605,7 @@ resolve_typedef (const char *s, struct fileloc *pos) if (strcmp (p->name, s) == 0) return p->type; error_at_line (pos, "unidentified type `%s'", s); - return &scalar_nonchar; /* treat as "int" */ + return &scalar_nonchar; /* treat as "int" */ } /* Create and return a new structure with tag NAME (or a union iff @@ -614,13 +622,11 @@ new_structure (const char *name, int isunion, struct fileloc *pos, /* temporary kludge - gengtype doesn't handle conditionals or macros. Ignore any attempt to define struct location_s, unless it is coming from this file (main() sets it up safely). */ - if (!strcmp (name, "location_s") && !isunion - && pos->file != this_file) + if (!strcmp (name, "location_s") && !isunion && pos->file != this_file) return find_structure (name, 0); for (si = structures; si != NULL; si = si->next) - if (strcmp (name, si->u.s.tag) == 0 - && UNION_P (si) == isunion) + if (strcmp (name, si->u.s.tag) == 0 && UNION_P (si) == isunion) { type_p ls = NULL; if (si->kind == TYPE_LANG_STRUCT) @@ -682,8 +688,7 @@ new_structure (const char *name, int isunion, struct fileloc *pos, /* Reset location_s's location to input.h so that we know where to write out its mark routine. */ - if (!strcmp (name, "location_s") && !isunion - && pos->file == this_file) + if (!strcmp (name, "location_s") && !isunion && pos->file == this_file) { size_t n; for (n = 0; n < num_gt_files; n++) @@ -695,7 +700,7 @@ new_structure (const char *name, int isunion, struct fileloc *pos, } } - return s; + return s; } /* Return the previously-defined structure with tag NAME (or a union @@ -708,8 +713,7 @@ find_structure (const char *name, int isunion) type_p s; for (s = structures; s != NULL; s = s->next) - if (strcmp (name, s->u.s.tag) == 0 - && UNION_P (s) == isunion) + if (strcmp (name, s->u.s.tag) == 0 && UNION_P (s) == isunion) return s; s = XCNEW (struct type); @@ -763,7 +767,7 @@ create_scalar_type (const char *name) type_p create_pointer (type_p t) { - if (! t->pointer_to) + if (!t->pointer_to) { type_p r = XCNEW (struct type); r->kind = TYPE_POINTER; @@ -796,7 +800,7 @@ create_option (options_p next, const char *name, const void *info) options_p o = XNEW (struct options); o->next = next; o->name = name; - o->info = (const char*) info; + o->info = (const char *) info; return o; } @@ -860,7 +864,7 @@ create_field_at (pair_p next, type_p type, const char *name, options_p opt, /* Create a fake field with the given type and name. NEXT is the next field in the chain. */ #define create_field(next,type,name) \ - create_field_all(next,type,name, 0, this_file, __LINE__) + create_field_all(next,type,name, 0, this_file, __LINE__) /* Like create_field, but the field is only valid when condition COND is true. */ @@ -885,11 +889,11 @@ create_optional_field_ (pair_p next, type_p type, const char *name, /* Create the field and give it the new fake union type. Add a "desc" tag that specifies the condition under which the field is valid. */ return create_field_all (next, union_type, name, - create_option (0, "desc", cond), - this_file, line); + create_option (0, "desc", cond), this_file, line); } + #define create_optional_field(next,type,name,cond) \ - create_optional_field_(next,type,name,cond,__LINE__) + create_optional_field_(next,type,name,cond,__LINE__) /* Reverse a linked list of 'struct pair's in place. */ pair_p @@ -904,27 +908,28 @@ nreverse_pairs (pair_p list) } return prev; } - + /* We don't care how long a CONST_DOUBLE is. */ #define CONST_DOUBLE_FORMAT "ww" /* We don't want to see codes that are only for generator files. */ #undef GENERATOR_FILE -enum rtx_code { +enum rtx_code +{ #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) ENUM , #include "rtl.def" #undef DEF_RTL_EXPR NUM_RTX_CODE }; -static const char * const rtx_name[NUM_RTX_CODE] = { +static const char *const rtx_name[NUM_RTX_CODE] = { #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) NAME , #include "rtl.def" #undef DEF_RTL_EXPR }; -static const char * const rtx_format[NUM_RTX_CODE] = { +static const char *const rtx_format[NUM_RTX_CODE] = { #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT , #include "rtl.def" #undef DEF_RTL_EXPR @@ -934,7 +939,8 @@ static int rtx_next_new[NUM_RTX_CODE]; /* We also need codes and names for insn notes (not register notes). Note that we do *not* bias the note values here. */ -enum insn_note { +enum insn_note +{ #define DEF_INSN_NOTE(NAME) NAME, #include "insn-notes.def" #undef DEF_INSN_NOTE @@ -944,7 +950,7 @@ enum insn_note { /* We must allocate one more entry here, as we use NOTE_INSN_MAX as the default field for line number notes. */ -static const char *const note_insn_name[NOTE_INSN_MAX+1] = { +static const char *const note_insn_name[NOTE_INSN_MAX + 1] = { #define DEF_INSN_NOTE(NAME) #NAME, #include "insn-notes.def" #undef DEF_INSN_NOTE @@ -992,8 +998,7 @@ write_rtx_next (void) oprintf (f, " 0,\n"); else oprintf (f, - " RTX_HDR_SIZE + %d * sizeof (rtunion),\n", - rtx_next_new[i]); + " RTX_HDR_SIZE + %d * sizeof (rtunion),\n", rtx_next_new[i]); oprintf (f, "};\n"); } @@ -1025,8 +1030,9 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) mem_attrs_tp = create_pointer (find_structure ("mem_attrs", 0)); reg_attrs_tp = create_pointer (find_structure ("reg_attrs", 0)); basic_block_tp = create_pointer (find_structure ("basic_block_def", 0)); - constant_tp = create_pointer (find_structure ("constant_descriptor_rtx", 0)); - scalar_tp = &scalar_nonchar; /* rtunion int */ + constant_tp = + create_pointer (find_structure ("constant_descriptor_rtx", 0)); + scalar_tp = &scalar_nonchar; /* rtunion int */ { pair_p note_flds = NULL; @@ -1109,8 +1115,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) t = scalar_tp, subname = "rt_int"; else if (i == CODE_LABEL && aindex == 4) t = rtx_tp, subname = "rt_rtx"; - else if (i == LABEL_REF - && (aindex == 1 || aindex == 2)) + else if (i == LABEL_REF && (aindex == 1 || aindex == 2)) t = rtx_tp, subname = "rt_rtx"; else if (i == NOTE && aindex == 4) t = note_union_tp, subname = ""; @@ -1139,7 +1144,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) else { error_at_line (&lexer_line, - "rtx type `%s' has `0' in position %lu, can't handle", + "rtx type `%s' has `0' in position %lu, can't handle", rtx_name[i], (unsigned long) aindex); t = &string_type; subname = "rt_int"; @@ -1177,9 +1182,9 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) default: error_at_line (&lexer_line, - "rtx type `%s' has `%c' in position %lu, can't handle", + "rtx type `%s' has `%c' in position %lu, can't handle", rtx_name[i], rtx_format[i][aindex], - (unsigned long)aindex); + (unsigned long) aindex); t = &string_type; subname = "rt_int"; break; @@ -1282,11 +1287,11 @@ adjust_field_type (type_p t, options_p opt) { int num = ISDIGIT (opt->name[5]) ? opt->name[5] - '0' : 0; - if (! UNION_OR_STRUCT_P (t) - && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p))) + if (!UNION_OR_STRUCT_P (t) + && (t->kind != TYPE_POINTER || !UNION_OR_STRUCT_P (t->u.p))) { error_at_line (&lexer_line, - "option `%s' may only be applied to structures or structure pointers", + "option `%s' may only be applied to structures or structure pointers", opt->name); return t; } @@ -1294,8 +1299,9 @@ adjust_field_type (type_p t, options_p opt) params_p = 1; if (params[num] != NULL) error_at_line (&lexer_line, "duplicate `%s' option", opt->name); - if (! ISDIGIT (opt->name[5])) - params[num] = create_pointer (CONST_CAST2(type_p, const char *, opt->info)); + if (!ISDIGIT (opt->name[5])) + params[num] = + create_pointer (CONST_CAST2 (type_p, const char *, opt->info)); else params[num] = CONST_CAST2 (type_p, const char *, opt->info); } @@ -1320,10 +1326,8 @@ adjust_field_type (type_p t, options_p opt) t = pointer_p ? create_pointer (realt) : realt; } - if (! length_p - && pointer_p - && t->u.p->kind == TYPE_SCALAR - && t->u.p->u.scalar_is_char) + if (!length_p + && pointer_p && t->u.p->kind == TYPE_SCALAR && t->u.p->u.scalar_is_char) return &string_type; if (t->kind == TYPE_ARRAY && t->u.a.p->kind == TYPE_POINTER && t->u.a.p->u.p->kind == TYPE_SCALAR @@ -1332,8 +1336,8 @@ adjust_field_type (type_p t, options_p opt) return t; } - + static void set_gc_used_type (type_p, enum gc_used_enum, type_p *); static void set_gc_used (pair_p); @@ -1341,7 +1345,8 @@ static void set_gc_used (pair_p); static void process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef, - int *pass_param, int *length, int *skip, type_p *nested_ptr) + int *pass_param, int *length, int *skip, + type_p *nested_ptr) { options_p o; for (o = opt; o; o = o->next) @@ -1403,7 +1408,7 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM]) set_gc_used_type (find_param_structure (f->type->u.p, param), GC_POINTED_TO, NULL); else if (skip) - ; /* target type is not used through this field */ + ; /* target type is not used through this field */ else set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL); } @@ -1522,7 +1527,7 @@ oprintf (outf_p o, const char *format, ...) va_start (ap, format); slength = vasprintf (&s, format, ap); - if (s == NULL || (int)slength < 0) + if (s == NULL || (int) slength < 0) fatal ("out of memory"); va_end (ap); @@ -1531,9 +1536,11 @@ oprintf (outf_p o, const char *format, ...) size_t new_len = o->buflength; if (new_len == 0) new_len = 1024; - do { - new_len *= 2; - } while (o->bufused + slength >= new_len); + do + { + new_len *= 2; + } + while (o->bufused + slength >= new_len); o->buf = XRESIZEVEC (char, o->buf, new_len); o->buflength = new_len; } @@ -1563,9 +1570,9 @@ open_base_files (void) /* gtype-desc.c is a little special, so we create it here. */ { /* The order of files here matters very much. */ - static const char *const ifiles [] = { + static const char *const ifiles[] = { "config.h", "system.h", "coretypes.h", "tm.h", - "hashtab.h", "splay-tree.h", "obstack.h", "bitmap.h", "input.h", + "hashtab.h", "splay-tree.h", "obstack.h", "bitmap.h", "input.h", "tree.h", "rtl.h", "function.h", "insn-config.h", "expr.h", "hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h", "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h", @@ -1596,7 +1603,7 @@ open_base_files (void) static const char * get_file_realbasename (const char *f) { - const char * lastslash = strrchr (f, '/'); + const char *lastslash = strrchr (f, '/'); return (lastslash != NULL) ? lastslash + 1 : f; } @@ -1621,7 +1628,7 @@ get_file_srcdir_relative_path (const char *f) static const char * get_file_basename (const char *f) { - const char * srcdir_path = get_file_srcdir_relative_path (f); + const char *srcdir_path = get_file_srcdir_relative_path (f); return (srcdir_path != NULL) ? srcdir_path : get_file_realbasename (f); } @@ -1637,7 +1644,7 @@ get_prefix_langdir_index (const char *f) for (lang_index = 0; lang_index < num_lang_dirs; lang_index++) { - const char * langdir = lang_dir_names [lang_index]; + const char *langdir = lang_dir_names[lang_index]; size_t langdir_len = strlen (langdir); if (f_len > langdir_len @@ -1660,18 +1667,17 @@ get_file_langdir (const char *f) srcdir relative, no point in looking further. */ int lang_index; - const char * srcdir_relative_path = get_file_srcdir_relative_path (f); - const char * r; + const char *srcdir_relative_path = get_file_srcdir_relative_path (f); + const char *r; if (!srcdir_relative_path) return NULL; lang_index = get_prefix_langdir_index (srcdir_relative_path); - if (lang_index < 0 - && strncmp (srcdir_relative_path, "c-family", 8) == 0) + if (lang_index < 0 && strncmp (srcdir_relative_path, "c-family", 8) == 0) r = "c-family"; else if (lang_index >= 0) - r = lang_dir_names [lang_index]; + r = lang_dir_names[lang_index]; else r = NULL; @@ -1689,7 +1695,7 @@ get_file_gtfilename (const char *f) const char *basename = get_file_realbasename (f); const char *langdir = get_file_langdir (f); - char * result = + char *result = (langdir ? xasprintf ("gt-%s-%s", langdir, basename) : xasprintf ("gt-%s", basename)); @@ -1700,7 +1706,7 @@ get_file_gtfilename (const char *f) char *s = result; for (; *s != '.'; s++) - if (! ISALNUM (*s) && *s != '-') + if (!ISALNUM (*s) && *s != '-') *s = '-'; memcpy (s, ".h", sizeof (".h")); @@ -1743,9 +1749,9 @@ get_output_file_with_visibility (const char *input_file) basename = get_file_basename (input_file); len = strlen (basename); - if ((len > 2 && memcmp (basename+len-2, ".c", 2) == 0) - || (len > 2 && memcmp (basename+len-2, ".y", 2) == 0) - || (len > 3 && memcmp (basename+len-3, ".in", 3) == 0)) + if ((len > 2 && memcmp (basename + len - 2, ".c", 2) == 0) + || (len > 2 && memcmp (basename + len - 2, ".y", 2) == 0) + || (len > 3 && memcmp (basename + len - 3, ".in", 3) == 0)) { output_name = get_file_gtfilename (input_file); for_name = basename; @@ -1772,7 +1778,8 @@ get_output_file_with_visibility (const char *input_file) else if (strncmp (basename, "cp", 2) == 0 && IS_DIR_SEPARATOR (basename[2]) && strcmp (basename + 3, "name-lookup.h") == 0) output_name = "gt-cp-name-lookup.h", for_name = "cp/name-lookup.c"; - else if (strncmp (basename, "objc", 4) == 0 && IS_DIR_SEPARATOR (basename[4]) + else if (strncmp (basename, "objc", 4) == 0 + && IS_DIR_SEPARATOR (basename[4]) && strcmp (basename + 5, "objc-act.h") == 0) output_name = "gt-objc-objc-act.h", for_name = "objc/objc-act.c"; else @@ -1805,7 +1812,7 @@ get_output_file_with_visibility (const char *input_file) const char * get_output_file_name (const char *input_file) { - outf_p o = get_output_file_with_visibility (input_file); + outf_p o = get_output_file_with_visibility (input_file); if (o) return o->name; return NULL; @@ -1848,23 +1855,24 @@ close_output_files (void) for (of = output_files; of; of = of->next) { - if (!is_file_equal(of)) - { - FILE *newfile = fopen (of->name, "w"); - if (newfile == NULL) - fatal ("opening output file %s: %s", of->name, xstrerror (errno)); - if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused) - fatal ("writing output file %s: %s", of->name, xstrerror (errno)); - if (fclose (newfile) != 0) - fatal ("closing output file %s: %s", of->name, xstrerror (errno)); - } - free(of->buf); + if (!is_file_equal (of)) + { + FILE *newfile = fopen (of->name, "w"); + if (newfile == NULL) + fatal ("opening output file %s: %s", of->name, xstrerror (errno)); + if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused) + fatal ("writing output file %s: %s", of->name, xstrerror (errno)); + if (fclose (newfile) != 0) + fatal ("closing output file %s: %s", of->name, xstrerror (errno)); + } + free (of->buf); of->buf = NULL; of->bufused = of->buflength = 0; } } -struct flist { +struct flist +{ struct flist *next; int started_p; const char *name; @@ -1877,10 +1885,8 @@ struct walk_type_data; For structures, given a pointer to the item in 'val'. For misc. pointers, given the item in 'val'. */ -typedef void (*process_field_fn) - (type_p f, const struct walk_type_data *p); -typedef void (*func_name_fn) - (type_p s, const struct walk_type_data *p); +typedef void (*process_field_fn) (type_p f, const struct walk_type_data * p); +typedef void (*func_name_fn) (type_p s, const struct walk_type_data * p); /* Parameters for write_types. */ @@ -1899,28 +1905,27 @@ static void output_escaped_param (struct walk_type_data *d, const char *, const char *); static void output_mangled_typename (outf_p, const_type_p); static void walk_type (type_p t, struct walk_type_data *d); -static void write_func_for_structure (type_p orig_s, type_p s, type_p * param, +static void write_func_for_structure (type_p orig_s, type_p s, type_p *param, const struct write_types_data *wtd); static void write_types_process_field - (type_p f, const struct walk_type_data *d); + (type_p f, const struct walk_type_data *d); static void write_types (outf_p output_header, - type_p structures, + type_p structures, type_p param_structs, const struct write_types_data *wtd); static void write_types_local_process_field - (type_p f, const struct walk_type_data *d); + (type_p f, const struct walk_type_data *d); static void write_local_func_for_structure - (const_type_p orig_s, type_p s, type_p * param); + (const_type_p orig_s, type_p s, type_p *param); static void write_local (outf_p output_header, - type_p structures, - type_p param_structs); + type_p structures, type_p param_structs); static void write_enum_defn (type_p structures, type_p param_structs); static int contains_scalar_p (type_p t); -static void put_mangled_filename (outf_p , const char *); +static void put_mangled_filename (outf_p, const char *); static void finish_root_table (struct flist *flp, const char *pfx, const char *tname, const char *lastname, const char *name); -static void write_root (outf_p , pair_p, type_p, const char *, int, +static void write_root (outf_p, pair_p, type_p, const char *, int, struct fileloc *, const char *, bool); static void write_array (outf_p f, pair_p v, const struct write_types_data *wtd); @@ -1955,35 +1960,37 @@ output_mangled_typename (outf_p of, const_type_p t) { if (t == NULL) oprintf (of, "Z"); - else switch (t->kind) - { - case TYPE_POINTER: - oprintf (of, "P"); - output_mangled_typename (of, t->u.p); - break; - case TYPE_SCALAR: - oprintf (of, "I"); - break; - case TYPE_STRING: - oprintf (of, "S"); - break; - case TYPE_STRUCT: - case TYPE_UNION: - case TYPE_LANG_STRUCT: - oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag), t->u.s.tag); - break; - case TYPE_PARAM_STRUCT: + else + switch (t->kind) { - int i; - for (i = 0; i < NUM_PARAM; i++) - if (t->u.param_struct.param[i] != NULL) - output_mangled_typename (of, t->u.param_struct.param[i]); - output_mangled_typename (of, t->u.param_struct.stru); + case TYPE_POINTER: + oprintf (of, "P"); + output_mangled_typename (of, t->u.p); + break; + case TYPE_SCALAR: + oprintf (of, "I"); + break; + case TYPE_STRING: + oprintf (of, "S"); + break; + case TYPE_STRUCT: + case TYPE_UNION: + case TYPE_LANG_STRUCT: + oprintf (of, "%lu%s", (unsigned long) strlen (t->u.s.tag), + t->u.s.tag); + break; + case TYPE_PARAM_STRUCT: + { + int i; + for (i = 0; i < NUM_PARAM; i++) + if (t->u.param_struct.param[i] != NULL) + output_mangled_typename (of, t->u.param_struct.param[i]); + output_mangled_typename (of, t->u.param_struct.stru); + } + break; + case TYPE_ARRAY: + gcc_unreachable (); } - break; - case TYPE_ARRAY: - gcc_unreachable (); - } } /* Print PARAM to D->OF processing escapes. D->VAL references the @@ -2000,30 +2007,31 @@ output_escaped_param (struct walk_type_data *d, const char *param, for (p = param; *p; p++) if (*p != '%') oprintf (d->of, "%c", *p); - else switch (*++p) - { - case 'h': - oprintf (d->of, "(%s)", d->prev_val[2]); - break; - case '0': - oprintf (d->of, "(%s)", d->prev_val[0]); - break; - case '1': - oprintf (d->of, "(%s)", d->prev_val[1]); - break; - case 'a': + else + switch (*++p) { - const char *pp = d->val + strlen (d->val); - while (pp[-1] == ']') - while (*pp != '[') - pp--; - oprintf (d->of, "%s", pp); + case 'h': + oprintf (d->of, "(%s)", d->prev_val[2]); + break; + case '0': + oprintf (d->of, "(%s)", d->prev_val[0]); + break; + case '1': + oprintf (d->of, "(%s)", d->prev_val[1]); + break; + case 'a': + { + const char *pp = d->val + strlen (d->val); + while (pp[-1] == ']') + while (*pp != '[') + pp--; + oprintf (d->of, "%s", pp); + } + break; + default: + error_at_line (d->line, "`%s' option contains bad escape %c%c", + oname, '%', *p); } - break; - default: - error_at_line (d->line, "`%s' option contains bad escape %c%c", - oname, '%', *p); - } } /* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL, @@ -2080,8 +2088,7 @@ walk_type (type_p t, struct walk_type_data *d) else if (strcmp (oo->name, "param_is") == 0) ; else if (strncmp (oo->name, "param", 5) == 0 - && ISDIGIT (oo->name[5]) - && strcmp (oo->name + 6, "_is") == 0) + && ISDIGIT (oo->name[5]) && strcmp (oo->name + 6, "_is") == 0) ; else if (strcmp (oo->name, "chain_next") == 0) ; @@ -2105,7 +2112,7 @@ walk_type (type_p t, struct walk_type_data *d) if (pointer_p) t = t->u.p; - if (! UNION_OR_STRUCT_P (t)) + if (!UNION_OR_STRUCT_P (t)) error_at_line (d->line, "`use_params' option on unimplemented type"); else t = find_param_structure (t, d->param); @@ -2129,12 +2136,11 @@ walk_type (type_p t, struct walk_type_data *d) t = nt; } else - error_at_line (d->line, "no parameter defined for `%s'", - d->val); + error_at_line (d->line, "no parameter defined for `%s'", d->val); } if (maybe_undef_p - && (t->kind != TYPE_POINTER || ! UNION_OR_STRUCT_P (t->u.p))) + && (t->kind != TYPE_POINTER || !UNION_OR_STRUCT_P (t->u.p))) { error_at_line (d->line, "field `%s' has invalid option `maybe_undef_p'\n", @@ -2151,16 +2157,15 @@ walk_type (type_p t, struct walk_type_data *d) case TYPE_POINTER: { - if (maybe_undef_p - && t->u.p->u.s.line.file == NULL) + if (maybe_undef_p && t->u.p->u.s.line.file == NULL) { oprintf (d->of, "%*sgcc_assert (!%s);\n", d->indent, "", d->val); break; } - if (! length) + if (!length) { - if (! UNION_OR_STRUCT_P (t->u.p) + if (!UNION_OR_STRUCT_P (t->u.p) && t->u.p->kind != TYPE_PARAM_STRUCT) { error_at_line (d->line, @@ -2173,12 +2178,11 @@ walk_type (type_p t, struct walk_type_data *d) { const char *oldprevval2 = d->prev_val[2]; - if (! UNION_OR_STRUCT_P (nested_ptr_d->type)) + if (!UNION_OR_STRUCT_P (nested_ptr_d->type)) { error_at_line (d->line, "field `%s' has invalid " - "option `nested_ptr'\n", - d->val); + "option `nested_ptr'\n", d->val); return; } @@ -2190,8 +2194,7 @@ walk_type (type_p t, struct walk_type_data *d) (nested_ptr_d->type->kind == TYPE_UNION ? "union" : "struct"), nested_ptr_d->type->u.s.tag, - d->fn_wants_lvalue ? "" : "const ", - d->val); + d->fn_wants_lvalue ? "" : "const ", d->val); oprintf (d->of, "%*s", d->indent + 2, ""); output_escaped_param (d, nested_ptr_d->convert_from, "nested_ptr"); @@ -2227,8 +2230,8 @@ walk_type (type_p t, struct walk_type_data *d) oprintf (d->of, "%*sif (%s != NULL) {\n", d->indent, "", d->val); d->indent += 2; oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter); - oprintf (d->of, "%*sfor (i%d = 0; i%d != (size_t)(", d->indent, "", - loopcounter, loopcounter); + oprintf (d->of, "%*sfor (i%d = 0; i%d != (size_t)(", d->indent, + "", loopcounter, loopcounter); output_escaped_param (d, length, "length"); oprintf (d->of, "); i%d++) {\n", loopcounter); d->indent += 2; @@ -2242,7 +2245,7 @@ walk_type (type_p t, struct walk_type_data *d) d->used_length = 0; d->indent -= 2; oprintf (d->of, "%*s}\n", d->indent, ""); - d->process_field(t, d); + d->process_field (t, d); d->indent -= 2; oprintf (d->of, "%*s}\n", d->indent, ""); } @@ -2306,7 +2309,7 @@ walk_type (type_p t, struct walk_type_data *d) int seen_default_p = 0; options_p o; - if (! t->u.s.line.file) + if (!t->u.s.line.file) error_at_line (d->line, "incomplete structure `%s'", t->u.s.tag); if ((d->bitmap & t->u.s.bitmap) != d->bitmap) @@ -2319,7 +2322,7 @@ walk_type (type_p t, struct walk_type_data *d) /* Some things may also be defined in the structure's options. */ for (o = t->u.s.opt; o; o = o->next) - if (! desc && strcmp (o->name, "desc") == 0) + if (!desc && strcmp (o->name, "desc") == 0) desc = o->info; d->prev_val[2] = oldval; @@ -2328,7 +2331,8 @@ walk_type (type_p t, struct walk_type_data *d) { if (desc == NULL) { - error_at_line (d->line, "missing `desc' option for union `%s'", + error_at_line (d->line, + "missing `desc' option for union `%s'", t->u.s.tag); desc = "1"; } @@ -2378,19 +2382,19 @@ walk_type (type_p t, struct walk_type_data *d) d->indent += 2; seen_default_p = 1; } - else if (! union_p && (default_p || tagid)) + else if (!union_p && (default_p || tagid)) error_at_line (d->line, "can't use `%s' outside a union on field `%s'", default_p ? "default" : "tag", f->name); - else if (union_p && ! (default_p || tagid) + else if (union_p && !(default_p || tagid) && f->type->kind == TYPE_SCALAR) { fprintf (stderr, - "%s:%d: warning: field `%s' is missing `tag' or `default' option\n", + "%s:%d: warning: field `%s' is missing `tag' or `default' option\n", d->line->file, d->line->line, f->name); continue; } - else if (union_p && ! (default_p || tagid)) + else if (union_p && !(default_p || tagid)) error_at_line (d->line, "field `%s' is missing `tag' or `default' option", f->name); @@ -2419,7 +2423,7 @@ walk_type (type_p t, struct walk_type_data *d) d->prev_val[1] = oldprevval1; d->prev_val[2] = oldprevval2; - if (union_p && ! seen_default_p) + if (union_p && !seen_default_p) { oprintf (d->of, "%*sdefault:\n", d->indent, ""); oprintf (d->of, "%*s break;\n", d->indent, ""); @@ -2492,8 +2496,7 @@ write_types_process_field (type_p f, const struct walk_type_data *d) oprintf (d->of, ", gt_e_"); output_mangled_typename (d->of, f); } - else if (UNION_OR_STRUCT_P (f) - && f->u.p->u.s.line.file != NULL) + else if (UNION_OR_STRUCT_P (f) && f->u.p->u.s.line.file != NULL) { oprintf (d->of, ", gt_ggc_e_"); output_mangled_typename (d->of, f); @@ -2555,7 +2558,7 @@ output_type_enum (outf_p of, type_p s) static outf_p get_output_file_for_structure (const_type_p s, type_p *param) { - const char * fn = s->u.s.line.file; + const char *fn = s->u.s.line.file; int i; /* This is a hack, and not the good kind either. */ @@ -2571,8 +2574,8 @@ get_output_file_for_structure (const_type_p s, type_p *param) PARAM, write out a routine that: - Takes a parameter, a void * but actually of type *S - If SEEN_ROUTINE returns nonzero, calls write_types_process_field on each - field of S or its substructures and (in some cases) things - that are pointed to by S. + field of S or its substructures and (in some cases) things + that are pointed to by S. */ static void @@ -2614,7 +2617,7 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param, d.bitmap = s->u.s.bitmap; d.param = param; d.prev_val[0] = "*x"; - d.prev_val[1] = "not valid postage"; /* Guarantee an error. */ + d.prev_val[1] = "not valid postage"; /* Guarantee an error. */ d.prev_val[3] = "x"; d.val = "(*x)"; @@ -2686,8 +2689,7 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param, oprintf (d.of, ");\n"); oprintf (d.of, " if (xprev == NULL) break;\n"); oprintf (d.of, " x = xprev;\n"); - oprintf (d.of, " (void) %s (xprev", - wtd->marker_routine); + oprintf (d.of, " (void) %s (xprev", wtd->marker_routine); if (wtd->param_prefix) { oprintf (d.of, ", xprev, gt_%s_", wtd->param_prefix); @@ -2749,13 +2751,11 @@ write_types (outf_p output_header, type_p structures, type_p param_structs, emitted afterwards. This is needed in plugin mode. */ oprintf (output_header, "/* macros and declarations */\n"); for (s = structures; s; s = s->next) - if (s->gc_used == GC_POINTED_TO - || s->gc_used == GC_MAYBE_POINTED_TO) + if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO) { options_p opt; - if (s->gc_used == GC_MAYBE_POINTED_TO - && s->u.s.line.file == NULL) + if (s->gc_used == GC_MAYBE_POINTED_TO && s->u.s.line.file == NULL) continue; oprintf (output_header, "#define gt_%s_", wtd->prefix); @@ -2764,16 +2764,14 @@ write_types (outf_p output_header, type_p structures, type_p param_structs, oprintf (output_header, " if (X != NULL) gt_%sx_%s (X);\\\n", wtd->prefix, s->u.s.tag); - oprintf (output_header, - " } while (0)\n"); + oprintf (output_header, " } while (0)\n"); for (opt = s->u.s.opt; opt; opt = opt->next) if (strcmp (opt->name, "ptr_alias") == 0) { const_type_p const t = (const_type_p) opt->info; if (t->kind == TYPE_STRUCT - || t->kind == TYPE_UNION - || t->kind == TYPE_LANG_STRUCT) + || t->kind == TYPE_UNION || t->kind == TYPE_LANG_STRUCT) oprintf (output_header, "#define gt_%sx_%s gt_%sx_%s\n", wtd->prefix, s->u.s.tag, wtd->prefix, t->u.s.tag); @@ -2819,13 +2817,11 @@ write_types (outf_p output_header, type_p structures, type_p param_structs, /* At last we emit the functions code. */ oprintf (output_header, "\n/* functions code */\n"); for (s = structures; s; s = s->next) - if (s->gc_used == GC_POINTED_TO - || s->gc_used == GC_MAYBE_POINTED_TO) + if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO) { options_p opt; - if (s->gc_used == GC_MAYBE_POINTED_TO - && s->u.s.line.file == NULL) + if (s->gc_used == GC_MAYBE_POINTED_TO && s->u.s.line.file == NULL) continue; for (opt = s->u.s.opt; opt; opt = opt->next) if (strcmp (opt->name, "ptr_alias") == 0) @@ -2860,15 +2856,13 @@ write_types (outf_p output_header, type_p structures, type_p param_structs, } } -static const struct write_types_data ggc_wtd = -{ +static const struct write_types_data ggc_wtd = { "ggc_m", NULL, "ggc_mark", "ggc_test_and_set_mark", NULL, "GC marker procedures. ", FALSE }; -static const struct write_types_data pch_wtd = -{ +static const struct write_types_data pch_wtd = { "pch_n", "pch_p", "gt_pch_note_object", "gt_pch_note_object", "gt_pch_note_reorder", "PCH type-walking procedures. ", @@ -2922,7 +2916,7 @@ write_local_func_for_structure (const_type_p orig_s, type_p s, type_p *param) d.bitmap = s->u.s.bitmap; d.param = param; d.prev_val[0] = d.prev_val[2] = "*x"; - d.prev_val[1] = "not valid postage"; /* Guarantee an error. */ + d.prev_val[1] = "not valid postage"; /* Guarantee an error. */ d.prev_val[3] = "x"; d.val = "(*x)"; d.fn_wants_lvalue = true; @@ -2955,8 +2949,7 @@ write_local (outf_p output_header, type_p structures, type_p param_structs) return; oprintf (output_header, "\n/* Local pointer-walking routines. */\n"); for (s = structures; s; s = s->next) - if (s->gc_used == GC_POINTED_TO - || s->gc_used == GC_MAYBE_POINTED_TO) + if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO) { options_p opt; @@ -2968,8 +2961,7 @@ write_local (outf_p output_header, type_p structures, type_p param_structs) { const_type_p const t = (const_type_p) opt->info; if (t->kind == TYPE_STRUCT - || t->kind == TYPE_UNION - || t->kind == TYPE_LANG_STRUCT) + || t->kind == TYPE_UNION || t->kind == TYPE_LANG_STRUCT) { oprintf (output_header, "#define gt_pch_p_"); output_mangled_typename (output_header, s); @@ -2989,7 +2981,7 @@ write_local (outf_p output_header, type_p structures, type_p param_structs) oprintf (output_header, "extern void gt_pch_p_"); output_mangled_typename (output_header, s); oprintf (output_header, - "\n (void *, void *, gt_pointer_operator, void *);\n"); + "\n (void *, void *, gt_pointer_operator, void *);\n"); if (s->kind == TYPE_LANG_STRUCT) { @@ -3004,14 +2996,14 @@ write_local (outf_p output_header, type_p structures, type_p param_structs) for (s = param_structs; s; s = s->next) if (s->gc_used == GC_POINTED_TO) { - type_p * param = s->u.param_struct.param; + type_p *param = s->u.param_struct.param; type_p stru = s->u.param_struct.stru; /* Declare the marker procedure. */ oprintf (output_header, "extern void gt_pch_p_"); output_mangled_typename (output_header, s); oprintf (output_header, - "\n (void *, void *, gt_pointer_operator, void *);\n"); + "\n (void *, void *, gt_pointer_operator, void *);\n"); if (stru->u.s.line.file == NULL) { @@ -3088,7 +3080,7 @@ contains_scalar_p (type_p t) return contains_scalar_p (t->u.a.p); default: /* Could also check for structures that have no non-pointer - fields, but there aren't enough of those to worry about. */ + fields, but there aren't enough of those to worry about. */ return 1; } } @@ -3135,8 +3127,7 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname, if (bitmap & 1) { oprintf (base_files[fnum], - "extern const struct %s gt_%s_", - tname, pfx); + "extern const struct %s gt_%s_", tname, pfx); put_mangled_filename (base_files[fnum], fli2->name); oprintf (base_files[fnum], "[];\n"); } @@ -3145,9 +3136,8 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname, { size_t fnum; for (fnum = 0; base_files && fnum < num_lang_dirs; fnum++) - oprintf (base_files [fnum], - "EXPORTED_CONST struct %s * const %s[] = {\n", - tname, name); + oprintf (base_files[fnum], + "EXPORTED_CONST struct %s * const %s[] = {\n", tname, name); } @@ -3244,13 +3234,13 @@ write_field_root (outf_p f, pair_p v, type_p type, const char *name, /* Write out to F the table entry and any marker routines needed to mark NAME as TYPE. V can be one of three values: - - null, if NAME is too complex to represent using a single - count and stride. In this case, it is an error for NAME to - contain any gc-ed data. + - null, if NAME is too complex to represent using a single + count and stride. In this case, it is an error for NAME to + contain any gc-ed data. - - the outermost array that contains NAME, if NAME is part of an array. + - the outermost array that contains NAME, if NAME is part of an array. - - the C variable that contains NAME, if NAME is not part of an array. + - the C variable that contains NAME, if NAME is not part of an array. LINE is the line of the C source that declares the root variable. HAS_LENGTH is nonzero iff V was a variable-length array. IF_MARKED @@ -3280,7 +3270,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, ; else error_at_line (line, - "field `%s' of global `%s' has unknown option `%s'", + "field `%s' of global `%s' has unknown option `%s'", fld->name, name, o->name); if (skip_p) @@ -3302,10 +3292,9 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, continue; if (validf != NULL) error_at_line (line, - "both `%s.%s.%s' and `%s.%s.%s' have tag `%s'", + "both `%s.%s.%s' and `%s.%s.%s' have tag `%s'", name, fld->name, validf->name, - name, fld->name, ufld->name, - tag); + name, fld->name, ufld->name, tag); validf = ufld; } if (validf != NULL) @@ -3316,7 +3305,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, } else if (desc) error_at_line (line, - "global `%s.%s' has `desc' option but is not union", + "global `%s.%s' has `desc' option but is not union", name, fld->name); else write_field_root (f, v, type, name, 0, line, if_marked, @@ -3344,7 +3333,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, tp = type->u.p; - if (! has_length && UNION_OR_STRUCT_P (tp)) + if (!has_length && UNION_OR_STRUCT_P (tp)) { oprintf (f, " >_ggc_mx_%s,\n", tp->u.s.tag); if (emit_pch) @@ -3352,7 +3341,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, else oprintf (f, " NULL"); } - else if (! has_length && tp->kind == TYPE_PARAM_STRUCT) + else if (!has_length && tp->kind == TYPE_PARAM_STRUCT) { oprintf (f, " >_ggc_m_"); output_mangled_typename (f, tp); @@ -3400,9 +3389,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, break; default: - error_at_line (line, - "global `%s' is unimplemented type", - name); + error_at_line (line, "global `%s' is unimplemented type", name); } } @@ -3428,8 +3415,7 @@ write_array (outf_p f, pair_p v, const struct write_types_data *wtd) if (wtd->param_prefix) { oprintf (f, "static void gt_%sa_%s\n", wtd->param_prefix, v->name); - oprintf (f, - " (void *, void *, gt_pointer_operator, void *);\n"); + oprintf (f, " (void *, void *, gt_pointer_operator, void *);\n"); oprintf (f, "static void gt_%sa_%s (ATTRIBUTE_UNUSED void *this_obj,\n", wtd->param_prefix, v->name); oprintf (d.of, @@ -3444,8 +3430,7 @@ write_array (outf_p f, pair_p v, const struct write_types_data *wtd) } d.opt = v->opt; - oprintf (f, "static void gt_%sa_%s (void *);\n", - wtd->prefix, v->name); + oprintf (f, "static void gt_%sa_%s (void *);\n", wtd->prefix, v->name); oprintf (f, "static void\ngt_%sa_%s (ATTRIBUTE_UNUSED void *x_p)\n", wtd->prefix, v->name); oprintf (f, "{\n"); @@ -3480,8 +3465,7 @@ write_roots (pair_p variables, bool emit_pch) else if (strcmp (o->name, "param_is") == 0) ; else if (strncmp (o->name, "param", 5) == 0 - && ISDIGIT (o->name[5]) - && strcmp (o->name + 6, "_is") == 0) + && ISDIGIT (o->name[5]) && strcmp (o->name + 6, "_is") == 0) ; else if (strcmp (o->name, "if_marked") == 0) ; @@ -3500,13 +3484,13 @@ write_roots (pair_p variables, bool emit_pch) fli->next = flp; fli->started_p = 0; fli->name = v->line.file; - gcc_assert(fli->name); + gcc_assert (fli->name); flp = fli; oprintf (f, "\n/* GC roots. */\n\n"); } - if (! deletable_p + if (!deletable_p && length && v->type->kind == TYPE_POINTER && (v->type->u.p->kind == TYPE_POINTER @@ -3538,7 +3522,7 @@ write_roots (pair_p variables, bool emit_pch) for (fli = flp; fli; fli = fli->next) if (fli->f == f) break; - if (! fli->started_p) + if (!fli->started_p) { fli->started_p = 1; @@ -3572,7 +3556,7 @@ write_roots (pair_p variables, bool emit_pch) for (fli = flp; fli; fli = fli->next) if (fli->f == f) break; - if (! fli->started_p) + if (!fli->started_p) { fli->started_p = 1; @@ -3609,14 +3593,15 @@ write_roots (pair_p variables, bool emit_pch) || v->type->u.p->kind != TYPE_PARAM_STRUCT || v->type->u.p->u.param_struct.stru != find_structure ("htab", 0)) { - error_at_line (&v->line, "if_marked option used but not hash table"); + error_at_line (&v->line, + "if_marked option used but not hash table"); continue; } for (fli = flp; fli; fli = fli->next) if (fli->f == f) break; - if (! fli->started_p) + if (!fli->started_p) { fli->started_p = 1; @@ -3649,13 +3634,13 @@ write_roots (pair_p variables, bool emit_pch) else if (strcmp (o->name, "if_marked") == 0) if_marked_p = 1; - if (! if_marked_p) + if (!if_marked_p) continue; for (fli = flp; fli; fli = fli->next) if (fli->f == f) break; - if (! fli->started_p) + if (!fli->started_p) { fli->started_p = 1; @@ -3685,13 +3670,13 @@ write_roots (pair_p variables, bool emit_pch) if (skip_p) continue; - if (! contains_scalar_p (v->type)) + if (!contains_scalar_p (v->type)) continue; for (fli = flp; fli; fli = fli->next) if (fli->f == f) break; - if (! fli->started_p) + if (!fli->started_p) { fli->started_p = 1; @@ -3726,7 +3711,7 @@ note_def_vec (const char *type_name, bool is_scalar, struct fileloc *pos) type_p t; options_p o; type_p len_ty = create_scalar_type ("unsigned"); - const char *name = concat ("VEC_", type_name, "_base", (char *)0); + const char *name = concat ("VEC_", type_name, "_base", (char *) 0); if (is_scalar) { @@ -3751,14 +3736,14 @@ note_def_vec (const char *type_name, bool is_scalar, struct fileloc *pos) we had expanded the macros in vec.h: typedef struct VEC_<type>_<astrat> { - VEC_<type>_base base; + VEC_<type>_base base; } VEC_<type>_<astrat>; */ void note_def_vec_alloc (const char *type, const char *astrat, struct fileloc *pos) { - const char *astratname = concat ("VEC_", type, "_", astrat, (char *)0); - const char *basename = concat ("VEC_", type, "_base", (char *)0); + const char *astratname = concat ("VEC_", type, "_", astrat, (char *) 0); + const char *basename = concat ("VEC_", type, "_base", (char *) 0); pair_p field = create_field_at (0, resolve_typedef (basename, pos), "base", 0, pos); @@ -3791,8 +3776,10 @@ variable_size_p (const type_p s) return false; } -enum alloc_quantity { single, vector }; -enum alloc_zone { any_zone, specific_zone }; +enum alloc_quantity +{ single, vector }; +enum alloc_zone +{ any_zone, specific_zone }; /* Writes one typed allocator definition for type identifier TYPE_NAME with optional type specifier TYPE_SPECIFIER. The allocator name will contain @@ -3802,15 +3789,15 @@ enum alloc_zone { any_zone, specific_zone }; the allocator will be zone-specific. */ static void -write_typed_alloc_def (bool variable_size, const char * type_specifier, - const char * type_name, const char * allocator_type, +write_typed_alloc_def (bool variable_size, const char *type_specifier, + const char *type_name, const char *allocator_type, enum alloc_quantity quantity, enum alloc_zone zone) { bool two_args = variable_size && (quantity == vector); bool third_arg = ((zone == specific_zone) && (variable_size || (quantity == vector))); - oprintf (header_file, "#define ggc_alloc_%s%s",allocator_type, type_name); + oprintf (header_file, "#define ggc_alloc_%s%s", allocator_type, type_name); oprintf (header_file, "(%s%s%s%s%s) ", (variable_size ? "SIZE" : ""), (two_args ? ", " : ""), @@ -3832,7 +3819,7 @@ write_typed_alloc_def (bool variable_size, const char * type_specifier, /* Writes a typed allocator definition for a struct or union S. */ static void -write_typed_struct_alloc_def (const type_p s, const char * allocator_type, +write_typed_struct_alloc_def (const type_p s, const char *allocator_type, enum alloc_quantity quantity, enum alloc_zone zone) { @@ -3843,7 +3830,7 @@ write_typed_struct_alloc_def (const type_p s, const char * allocator_type, /* Writes a typed allocator definition for a typedef P. */ static void -write_typed_typedef_alloc_def (const pair_p p, const char * allocator_type, +write_typed_typedef_alloc_def (const pair_p p, const char *allocator_type, enum alloc_quantity quantity, enum alloc_zone zone) { @@ -3924,15 +3911,16 @@ output_typename (outf_p of, const_type_p t) { int i; for (i = 0; i < NUM_PARAM; i++) - if (t->u.param_struct.param[i] != NULL) { - output_typename (of, t->u.param_struct.param[i]); - oprintf (of, "_"); - } + if (t->u.param_struct.param[i] != NULL) + { + output_typename (of, t->u.param_struct.param[i]); + oprintf (of, "_"); + } output_typename (of, t->u.param_struct.stru); break; } default: - gcc_unreachable(); + gcc_unreachable (); } } @@ -3942,7 +3930,7 @@ output_typename (outf_p of, const_type_p t) static void write_splay_tree_allocator_def (const_type_p s) { - outf_p of = get_output_file_for_structure(s, NULL); + outf_p of = get_output_file_for_structure (s, NULL); oprintf (of, "void * ggc_alloc_splay_tree_"); output_typename (of, s); oprintf (of, " (int sz, void * nl)\n"); @@ -3987,15 +3975,32 @@ dump_typekind (int indent, enum typekind kind) printf ("%*ckind = ", indent, ' '); switch (kind) { - case TYPE_SCALAR: printf ("TYPE_SCALAR"); break; - case TYPE_STRING: printf ("TYPE_STRING"); break; - case TYPE_STRUCT: printf ("TYPE_STRUCT"); break; - case TYPE_UNION: printf ("TYPE_UNION"); break; - case TYPE_POINTER: printf ("TYPE_POINTER"); break; - case TYPE_ARRAY: printf ("TYPE_ARRAY"); break; - case TYPE_LANG_STRUCT: printf ("TYPE_LANG_STRUCT"); break; - case TYPE_PARAM_STRUCT: printf ("TYPE_PARAM_STRUCT"); break; - default: gcc_unreachable (); + case TYPE_SCALAR: + printf ("TYPE_SCALAR"); + break; + case TYPE_STRING: + printf ("TYPE_STRING"); + break; + case TYPE_STRUCT: + printf ("TYPE_STRUCT"); + break; + case TYPE_UNION: + printf ("TYPE_UNION"); + break; + case TYPE_POINTER: + printf ("TYPE_POINTER"); + break; + case TYPE_ARRAY: + printf ("TYPE_ARRAY"); + break; + case TYPE_LANG_STRUCT: + printf ("TYPE_LANG_STRUCT"); + break; + case TYPE_PARAM_STRUCT: + printf ("TYPE_PARAM_STRUCT"); + break; + default: + gcc_unreachable (); } printf ("\n"); } @@ -4008,11 +4013,20 @@ dump_gc_used (int indent, enum gc_used_enum gc_used) printf ("%*cgc_used = ", indent, ' '); switch (gc_used) { - case GC_UNUSED: printf ("GC_UNUSED"); break; - case GC_USED: printf ("GC_USED"); break; - case GC_MAYBE_POINTED_TO: printf ("GC_MAYBE_POINTED_TO"); break; - case GC_POINTED_TO: printf ("GC_POINTED_TO"); break; - default: gcc_unreachable (); + case GC_UNUSED: + printf ("GC_UNUSED"); + break; + case GC_USED: + printf ("GC_USED"); + break; + case GC_MAYBE_POINTED_TO: + printf ("GC_MAYBE_POINTED_TO"); + break; + case GC_POINTED_TO: + printf ("GC_POINTED_TO"); + break; + default: + gcc_unreachable (); } printf ("\n"); } @@ -4027,8 +4041,8 @@ dump_options (int indent, options_p opt) o = opt; while (o) { - printf ("%s:%s ", o->name, o->info); - o = o->next; + printf ("%s:%s ", o->name, o->info); + o = o->next; } printf ("\n"); } @@ -4058,8 +4072,8 @@ dump_type_u_s (int indent, type_p t) fields = t->u.s.fields; while (fields) { - dump_pair (indent + INDENT, fields); - fields = fields->next; + dump_pair (indent + INDENT, fields); + fields = fields->next; } printf ("%*cend of fields of type %p\n", indent, ' ', (void *) t); dump_options (indent, t->u.s.opt); @@ -4122,7 +4136,7 @@ dump_type (int indent, type_p t) { PTR *slot; - printf ("%*cType at %p: ", indent, ' ', (void *)t); + printf ("%*cType at %p: ", indent, ' ', (void *) t); slot = htab_find_slot (seen_types, t, INSERT); if (*slot != NULL) { @@ -4134,7 +4148,7 @@ dump_type (int indent, type_p t) dump_typekind (indent, t->kind); printf ("%*cpointer_to = %p\n", indent + INDENT, ' ', - (void *)t->pointer_to); + (void *) t->pointer_to); dump_gc_used (indent + INDENT, t->gc_used); switch (t->kind) { @@ -4162,7 +4176,7 @@ dump_type (int indent, type_p t) default: gcc_unreachable (); } - printf ("%*cEnd of type at %p\n", indent, ' ', (void *)t); + printf ("%*cEnd of type at %p\n", indent, ' ', (void *) t); } /* Dumps the pair P. */ @@ -4180,7 +4194,7 @@ dump_pair (int indent, pair_p p) /* Dumps the list of pairs PP. */ static void -dump_pair_list (const char * name, pair_p pp) +dump_pair_list (const char *name, pair_p pp) { pair_p p; printf ("%s:\n", name); @@ -4192,7 +4206,7 @@ dump_pair_list (const char * name, pair_p pp) /* Dumps the STRUCTURES. */ static void -dump_structures (const char * name, type_p structures) +dump_structures (const char *name, type_p structures) { printf ("%s:\n", name); dump_type_list (0, structures); @@ -4211,17 +4225,17 @@ dump_everything (void) dump_pair_list ("variables", variables); htab_delete (seen_types); } - + int main (int argc, char **argv) { size_t i; static struct fileloc pos = { this_file, 0 }; - char* inputlist = 0; + char *inputlist = 0; int do_dump = 0; outf_p output_header; - char* plugin_output_filename = NULL; + char *plugin_output_filename = NULL; /* fatal uses this */ progname = "gengtype"; @@ -4241,14 +4255,14 @@ main (int argc, char **argv) nb_plugin_files = argc - 5; plugin_files = XCNEWVEC (char *, nb_plugin_files); for (i = 0; i < nb_plugin_files; i++) - { - /* Place an all zero lang_bitmap before the plugin file - name. */ - char *name = argv[i + 5]; - int len = strlen(name) + 1 + sizeof (lang_bitmap); - plugin_files[i] = XCNEWVEC (char, len) + sizeof (lang_bitmap); - strcpy (plugin_files[i], name); - } + { + /* Place an all zero lang_bitmap before the plugin file + name. */ + char *name = argv[i + 5]; + int len = strlen (name) + 1 + sizeof (lang_bitmap); + plugin_files[i] = XCNEWVEC (char, len) + sizeof (lang_bitmap); + strcpy (plugin_files[i], name); + } } else if (argc == 3) { @@ -4257,7 +4271,7 @@ main (int argc, char **argv) } else fatal ("usage: gengtype [-d] [-P pluginout.h] srcdir input-list " - "[file1 file2 ... fileN]"); + "[file1 file2 ... fileN]"); srcdir_len = strlen (srcdir); @@ -4272,15 +4286,24 @@ main (int argc, char **argv) /* These types are set up with #define or else outside of where we can see them. */ pos.line = __LINE__ + 1; - do_scalar_typedef ("CUMULATIVE_ARGS", &pos); pos.line++; - do_scalar_typedef ("REAL_VALUE_TYPE", &pos); pos.line++; - do_scalar_typedef ("FIXED_VALUE_TYPE", &pos); pos.line++; - do_scalar_typedef ("double_int", &pos); pos.line++; - do_scalar_typedef ("uint64_t", &pos); pos.line++; - do_scalar_typedef ("uint8", &pos); pos.line++; - do_scalar_typedef ("jword", &pos); pos.line++; - do_scalar_typedef ("JCF_u2", &pos); pos.line++; - do_scalar_typedef ("void", &pos); pos.line++; + do_scalar_typedef ("CUMULATIVE_ARGS", &pos); + pos.line++; + do_scalar_typedef ("REAL_VALUE_TYPE", &pos); + pos.line++; + do_scalar_typedef ("FIXED_VALUE_TYPE", &pos); + pos.line++; + do_scalar_typedef ("double_int", &pos); + pos.line++; + do_scalar_typedef ("uint64_t", &pos); + pos.line++; + do_scalar_typedef ("uint8", &pos); + pos.line++; + do_scalar_typedef ("jword", &pos); + pos.line++; + do_scalar_typedef ("JCF_u2", &pos); + pos.line++; + do_scalar_typedef ("void", &pos); + pos.line++; do_typedef ("PTR", create_pointer (resolve_typedef ("void", &pos)), &pos); for (i = 0; i < num_gt_files; i++) @@ -4310,11 +4333,11 @@ main (int argc, char **argv) dump_everything (); if (plugin_files) - { - for (i = 0; i < nb_plugin_files; i++) - free (plugin_files[i] - sizeof (lang_bitmap)); - free (plugin_files); - } + { + for (i = 0; i < nb_plugin_files; i++) + free (plugin_files[i] - sizeof (lang_bitmap)); + free (plugin_files); + } if (hit_error) return 1; diff --git a/gcc/gengtype.h b/gcc/gengtype.h index 75e4e2d5c43..304d3b17ae4 100644 --- a/gcc/gengtype.h +++ b/gcc/gengtype.h @@ -1,28 +1,29 @@ /* Process source files and output type information. Copyright (C) 2002, 2003, 2004, 2007, 2008 Free Software Foundation, Inc. -This file is part of GCC. + 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 3, or (at your option) any later -version. + 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 3, 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. + 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 COPYING3. If not see -<http://www.gnu.org/licenses/>. */ + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ #ifndef GCC_GENGTYPE_H #define GCC_GENGTYPE_H /* A file position, mostly for error messages. The FILE element may be compared using pointer equality. */ -struct fileloc { +struct fileloc +{ const char *file; int line; }; @@ -39,10 +40,12 @@ extern struct fileloc lexer_line; /* Print an error message. */ extern void error_at_line - (const struct fileloc *pos, const char *msg, ...) ATTRIBUTE_PRINTF_2; +(const struct fileloc *pos, const char *msg, ...) ATTRIBUTE_PRINTF_2; /* Like asprintf, but calls fatal() on out of memory. */ -extern char *xasprintf(const char *, ...) ATTRIBUTE_PRINTF_1; +extern char * +xasprintf (const char *, ...) + ATTRIBUTE_PRINTF_1; /* Constructor routines for types. */ extern void do_typedef (const char *s, type_p t, struct fileloc *pos); @@ -55,11 +58,14 @@ extern type_p find_structure (const char *s, int isunion); extern type_p create_scalar_type (const char *name); extern type_p create_pointer (type_p t); extern type_p create_array (type_p t, const char *len); -extern options_p create_option (options_p, const char *name, const void *info); +extern options_p create_option (options_p, const char *name, + const void *info); extern options_p create_nested_ptr_option (options_p, type_p t, - const char *from, const char *to); -extern pair_p create_field_at (pair_p next, type_p type, const char *name, - options_p opt, struct fileloc *pos); + const char *from, + const char *to); +extern pair_p create_field_at (pair_p next, type_p type, + const char *name, options_p opt, + struct fileloc *pos); extern pair_p nreverse_pairs (pair_p list); extern type_p adjust_field_type (type_p, options_p); extern void note_variable (const char *s, type_p t, options_p o, @@ -77,37 +83,38 @@ extern void parse_file (const char *name); extern bool hit_error; /* Token codes. */ -enum { - EOF_TOKEN = 0, - - /* Per standard convention, codes in the range (0, UCHAR_MAX] - represent single characters with those character codes. */ - - CHAR_TOKEN_OFFSET = UCHAR_MAX + 1, - GTY_TOKEN = CHAR_TOKEN_OFFSET, - TYPEDEF, - EXTERN, - STATIC, - UNION, - STRUCT, - ENUM, - VEC_TOKEN, - DEFVEC_OP, - DEFVEC_I, - DEFVEC_ALLOC, - ELLIPSIS, - PTR_ALIAS, - NESTED_PTR, - PARAM_IS, - NUM, - SCALAR, - ID, - STRING, - CHAR, - ARRAY, - - /* print_token assumes that any token >= FIRST_TOKEN_WITH_VALUE may have - a meaningful value to be printed. */ - FIRST_TOKEN_WITH_VALUE = PARAM_IS -}; +enum + { + EOF_TOKEN = 0, + + /* Per standard convention, codes in the range (0, UCHAR_MAX] + represent single characters with those character codes. */ + + CHAR_TOKEN_OFFSET = UCHAR_MAX + 1, + GTY_TOKEN = CHAR_TOKEN_OFFSET, + TYPEDEF, + EXTERN, + STATIC, + UNION, + STRUCT, + ENUM, + VEC_TOKEN, + DEFVEC_OP, + DEFVEC_I, + DEFVEC_ALLOC, + ELLIPSIS, + PTR_ALIAS, + NESTED_PTR, + PARAM_IS, + NUM, + SCALAR, + ID, + STRING, + CHAR, + ARRAY, + + /* print_token assumes that any token >= FIRST_TOKEN_WITH_VALUE may have + a meaningful value to be printed. */ + FIRST_TOKEN_WITH_VALUE = PARAM_IS + }; #endif diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index d6e35807d05..8bad08d567a 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -31,6 +31,61 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-propagate.h" #include "target.h" +/* Return true when DECL is static object in other partition. + In that case we must prevent folding as we can't refer to + the symbol. + + We can get into it in two ways: + 1) When analyzing C++ virtual tables. + C++ virtual tables do have known constructors even + when they are keyed to other compilation unit. + Those tables can contain pointers to methods and vars + in other units. Those methods have both STATIC and EXTERNAL + set. + 2) In WHOPR mode devirtualization might lead to reference + to method that was partitioned elsehwere. + In this case we have static VAR_DECL or FUNCTION_DECL + that has no corresponding callgraph/varpool node + declaring the body. */ + +static bool +static_object_in_other_unit_p (tree decl) +{ + struct varpool_node *vnode; + struct cgraph_node *node; + + if (!TREE_STATIC (decl) + || TREE_PUBLIC (decl) || DECL_COMDAT (decl)) + return false; + /* External flag is set, so we deal with C++ reference + to static object from other file. */ + if (DECL_EXTERNAL (decl)) + { + /* Just be sure it is not big in frontend setting + flags incorrectly. Those variables should never + be finalized. */ + gcc_checking_assert (!(vnode = varpool_get_node (decl)) + || !vnode->finalized); + return true; + } + /* We are not at ltrans stage; so don't worry about WHOPR. */ + if (!flag_ltrans) + return false; + if (TREE_CODE (decl) == FUNCTION_DECL) + { + node = cgraph_get_node (decl); + if (!node || !node->analyzed) + return true; + } + else if (TREE_CODE (decl) == VAR_DECL) + { + vnode = varpool_get_node (decl); + if (!vnode || !vnode->finalized) + return true; + } + return false; +} + /* CVAL is value taken from DECL_INITIAL of variable. Try to transorm it into acceptable form for is_gimple_min_invariant. */ @@ -50,6 +105,11 @@ canonicalize_constructor_val (tree cval) if (TREE_CODE (cval) == ADDR_EXPR) { tree base = get_base_address (TREE_OPERAND (cval, 0)); + if (base + && (TREE_CODE (base) == VAR_DECL + || TREE_CODE (base) == FUNCTION_DECL) + && static_object_in_other_unit_p (base)) + return NULL_TREE; if (base && TREE_CODE (base) == VAR_DECL) add_referenced_var (base); } @@ -62,16 +122,16 @@ canonicalize_constructor_val (tree cval) tree get_symbol_constant_value (tree sym) { - if ((TREE_STATIC (sym) || DECL_EXTERNAL (sym)) - && (TREE_CODE (sym) == CONST_DECL - || varpool_get_node (sym)->const_value_known)) + if (const_value_known_p (sym)) { tree val = DECL_INITIAL (sym); if (val) { val = canonicalize_constructor_val (val); - if (is_gimple_min_invariant (val)) + if (val && is_gimple_min_invariant (val)) return val; + else + return NULL_TREE; } /* Variables declared 'const' without an initializer have zero as the initializer if they may not be @@ -1370,7 +1430,6 @@ gimple_fold_obj_type_ref_known_binfo (HOST_WIDE_INT token, tree known_binfo) { HOST_WIDE_INT i; tree v, fndecl; - struct cgraph_node *node; v = BINFO_VIRTUALS (known_binfo); i = 0; @@ -1382,13 +1441,11 @@ gimple_fold_obj_type_ref_known_binfo (HOST_WIDE_INT token, tree known_binfo) } fndecl = TREE_VALUE (v); - node = cgraph_get_node (fndecl); /* When cgraph node is missing and function is not public, we cannot devirtualize. This can happen in WHOPR when the actual method ends up in other partition, because we found devirtualization possibility too late. */ - if ((!node || (!node->analyzed && !node->in_other_partition)) - && (!TREE_PUBLIC (fndecl) || DECL_COMDAT (fndecl))) + if (static_object_in_other_unit_p (fndecl)) return NULL; return build_fold_addr_expr (fndecl); } @@ -1414,6 +1471,9 @@ gimple_fold_obj_type_ref (tree ref, tree known_type) if (binfo) { HOST_WIDE_INT token = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1); + /* If there is no virtual methods fold this to an indirect call. */ + if (!BINFO_VIRTUALS (binfo)) + return OBJ_TYPE_REF_EXPR (ref); return gimple_fold_obj_type_ref_known_binfo (token, binfo); } else @@ -1426,7 +1486,7 @@ gimple_fold_obj_type_ref (tree ref, tree known_type) It is assumed that the operands have been previously folded. */ static bool -fold_gimple_call (gimple_stmt_iterator *gsi) +fold_gimple_call (gimple_stmt_iterator *gsi, bool inplace) { gimple stmt = gsi_stmt (*gsi); @@ -1434,7 +1494,7 @@ fold_gimple_call (gimple_stmt_iterator *gsi) /* Check for builtins that CCP can handle using information not available in the generic fold routines. */ - if (callee && DECL_BUILT_IN (callee)) + if (!inplace && callee && DECL_BUILT_IN (callee)) { tree result = gimple_fold_builtin (stmt); @@ -1451,7 +1511,6 @@ fold_gimple_call (gimple_stmt_iterator *gsi) there requires that we create a new CALL_EXPR, and that requires copying EH region info to the new node. Easier to just do it here where we can just smash the call operand. */ - /* ??? Is there a good reason not to do this in fold_stmt_inplace? */ callee = gimple_call_fn (stmt); if (TREE_CODE (callee) == OBJ_TYPE_REF && TREE_CODE (OBJ_TYPE_REF_OBJECT (callee)) == ADDR_EXPR) @@ -1518,9 +1577,7 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace) changed = true; } } - /* The entire statement may be replaced in this case. */ - if (!inplace) - changed |= fold_gimple_call (gsi); + changed |= fold_gimple_call (gsi, inplace); break; case GIMPLE_ASM: diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 595316043c5..994ffdecea2 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2479,8 +2479,11 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) { /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we have to do is replicate it as a GIMPLE_CALL tuple. */ + gimple_stmt_iterator gsi; call = gimple_build_call_from_tree (*expr_p); gimplify_seq_add_stmt (pre_p, call); + gsi = gsi_last (*pre_p); + fold_stmt (&gsi); *expr_p = NULL_TREE; } @@ -4197,9 +4200,18 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, This kind of code arises in C++ when an object is bound to a const reference, and if "x" is a TARGET_EXPR we want to take advantage of the optimization below. */ + bool volatile_p = TREE_THIS_VOLATILE (*from_p); tree t = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)); if (t) { + if (TREE_THIS_VOLATILE (t) != volatile_p) + { + if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration) + t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p), + build_fold_addr_expr (t)); + if (REFERENCE_CLASS_P (t)) + TREE_THIS_VOLATILE (t) = volatile_p; + } *from_p = t; ret = GS_OK; changed = true; @@ -6797,8 +6809,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_gimple_reg, fb_rvalue); - recalculate_side_effects (*expr_p); + if (ret == GS_ERROR) + break; + recalculate_side_effects (*expr_p); *expr_p = fold_build2_loc (input_location, MEM_REF, TREE_TYPE (*expr_p), TREE_OPERAND (*expr_p, 0), @@ -6823,6 +6837,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_gimple_mem_ref_addr, fb_rvalue); + if (ret == GS_ERROR) + break; recalculate_side_effects (*expr_p); ret = GS_ALL_DONE; break; diff --git a/gcc/graphite-dependences.c b/gcc/graphite-dependences.c index 6296bfc2f3d..8c7a642a7ea 100644 --- a/gcc/graphite-dependences.c +++ b/gcc/graphite-dependences.c @@ -950,7 +950,7 @@ dot_deps_1 (FILE *file, scop_p scop) /* Display all the data dependences in SCoP using dotty. */ -void +DEBUG_FUNCTION void dot_deps (scop_p scop) { /* When debugging, enable the following code. This cannot be used @@ -971,7 +971,7 @@ dot_deps (scop_p scop) /* Display all the statement dependences in SCoP using dotty. */ -void +DEBUG_FUNCTION void dot_deps_stmt (scop_p scop) { /* When debugging, enable the following code. This cannot be used diff --git a/gcc/graphite-poly.c b/gcc/graphite-poly.c index ae6ad4451ae..ffd01f92d52 100644 --- a/gcc/graphite-poly.c +++ b/gcc/graphite-poly.c @@ -1269,7 +1269,7 @@ dot_lst_1 (FILE *file, lst_p lst) /* Display the LST using dotty. */ -void +DEBUG_FUNCTION void dot_lst (lst_p lst) { /* When debugging, enable the following code. This cannot be used diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c index e2847b88be5..bd0f7bd6f97 100644 --- a/gcc/graphite-scop-detection.c +++ b/gcc/graphite-scop-detection.c @@ -1489,7 +1489,7 @@ dot_all_scops_1 (FILE *file, VEC (scop_p, heap) *scops) /* Display all SCoPs using dotty. */ -void +DEBUG_FUNCTION void dot_all_scops (VEC (scop_p, heap) *scops) { /* When debugging, enable the following code. This cannot be used @@ -1510,7 +1510,7 @@ dot_all_scops (VEC (scop_p, heap) *scops) /* Display all SCoPs using dotty. */ -void +DEBUG_FUNCTION void dot_scop (scop_p scop) { VEC (scop_p, heap) *scops = NULL; diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 9aff583ae45..4e3a6850b8c 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -101,7 +101,6 @@ static int noce_find_if_block (basic_block, edge, edge, int); static int cond_exec_find_if_block (ce_if_block_t *); static int find_if_case_1 (basic_block, edge, edge); static int find_if_case_2 (basic_block, edge, edge); -static int find_memory (rtx *, void *); static int dead_or_predicable (basic_block, basic_block, basic_block, basic_block, int); static void noce_emit_move_insn (rtx, rtx); @@ -3882,15 +3881,6 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge) return TRUE; } -/* A subroutine of dead_or_predicable called through for_each_rtx. - Return 1 if a memory is found. */ - -static int -find_memory (rtx *px, void *data ATTRIBUTE_UNUSED) -{ - return MEM_P (*px); -} - /* Used by the code above to perform the actual rtl transformations. Return TRUE if successful. @@ -3992,131 +3982,38 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb, earliest = jump; } #endif + /* If we allocated new pseudos (e.g. in the conditional move + expander called from noce_emit_cmove), we must resize the + array first. */ + if (max_regno < max_reg_num ()) + max_regno = max_reg_num (); + /* Try the NCE path if the CE path did not result in any changes. */ if (n_validated_changes == 0) { + rtx cond; + regset live; + bool success; + /* In the non-conditional execution case, we have to verify that there are no trapping operations, no calls, no references to memory, and that any registers modified are dead at the branch site. */ - rtx insn, cond, prev; - bitmap merge_set, merge_set_noclobber, test_live, test_set; - unsigned i, fail = 0; - bitmap_iterator bi; - - /* Check for no calls or trapping operations. */ - for (insn = head; ; insn = NEXT_INSN (insn)) - { - if (CALL_P (insn)) - return FALSE; - if (NONDEBUG_INSN_P (insn)) - { - if (may_trap_p (PATTERN (insn))) - return FALSE; - - /* ??? Even non-trapping memories such as stack frame - references must be avoided. For stores, we collect - no lifetime info; for reads, we'd have to assert - true_dependence false against every store in the - TEST range. */ - if (for_each_rtx (&PATTERN (insn), find_memory, NULL)) - return FALSE; - } - if (insn == end) - break; - } - - if (! any_condjump_p (jump)) + if (!any_condjump_p (jump)) return FALSE; /* Find the extent of the conditional. */ cond = noce_get_condition (jump, &earliest, false); - if (! cond) + if (!cond) return FALSE; - /* Collect: - MERGE_SET = set of registers set in MERGE_BB - MERGE_SET_NOCLOBBER = like MERGE_SET, but only includes registers - that are really set, not just clobbered. - TEST_LIVE = set of registers live at EARLIEST - TEST_SET = set of registers set between EARLIEST and the - end of the block. */ - - merge_set = BITMAP_ALLOC (®_obstack); - merge_set_noclobber = BITMAP_ALLOC (®_obstack); - test_live = BITMAP_ALLOC (®_obstack); - test_set = BITMAP_ALLOC (®_obstack); - - /* ??? bb->local_set is only valid during calculate_global_regs_live, - so we must recompute usage for MERGE_BB. Not so bad, I suppose, - since we've already asserted that MERGE_BB is small. */ - /* If we allocated new pseudos (e.g. in the conditional move - expander called from noce_emit_cmove), we must resize the - array first. */ - if (max_regno < max_reg_num ()) - max_regno = max_reg_num (); - - FOR_BB_INSNS (merge_bb, insn) - { - if (NONDEBUG_INSN_P (insn)) - { - df_simulate_find_defs (insn, merge_set); - df_simulate_find_noclobber_defs (insn, merge_set_noclobber); - } - } - - /* For small register class machines, don't lengthen lifetimes of - hard registers before reload. */ - if (! reload_completed - && targetm.small_register_classes_for_mode_p (VOIDmode)) - { - EXECUTE_IF_SET_IN_BITMAP (merge_set_noclobber, 0, i, bi) - { - if (i < FIRST_PSEUDO_REGISTER - && ! fixed_regs[i] - && ! global_regs[i]) - fail = 1; - } - } - - /* For TEST, we're interested in a range of insns, not a whole block. - Moreover, we're interested in the insns live from OTHER_BB. */ - - /* The loop below takes the set of live registers - after JUMP, and calculates the live set before EARLIEST. */ - bitmap_copy (test_live, df_get_live_in (other_bb)); - df_simulate_initialize_backwards (test_bb, test_live); - for (insn = jump; ; insn = prev) - { - if (INSN_P (insn)) - { - df_simulate_find_defs (insn, test_set); - df_simulate_one_insn_backwards (test_bb, insn, test_live); - } - prev = PREV_INSN (insn); - if (insn == earliest) - break; - } - - /* We can perform the transformation if - MERGE_SET_NOCLOBBER & TEST_SET - and - MERGE_SET & TEST_LIVE) - and - TEST_SET & DF_LIVE_IN (merge_bb) - are empty. */ - - if (bitmap_intersect_p (test_set, merge_set_noclobber) - || bitmap_intersect_p (test_live, merge_set) - || bitmap_intersect_p (test_set, df_get_live_in (merge_bb))) - fail = 1; - - BITMAP_FREE (merge_set_noclobber); - BITMAP_FREE (merge_set); - BITMAP_FREE (test_live); - BITMAP_FREE (test_set); - - if (fail) + live = BITMAP_ALLOC (®_obstack); + simulate_backwards_to_point (merge_bb, live, end); + success = can_move_insns_across (head, end, earliest, jump, + merge_bb, live, + df_get_live_in (other_bb), NULL); + BITMAP_FREE (live); + if (!success) return FALSE; } diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 964d03ba21a..21e0b647973 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -251,6 +251,12 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, In that case just go ahead and re-use it. */ if (!e->callee->callers->next_caller && cgraph_can_remove_if_no_direct_calls_p (e->callee) + /* Inlining might enable more devirtualizing, so we want to remove + those only after all devirtualizable virtual calls are processed. + Lacking may edges in callgraph we just preserve them post + inlining. */ + && (!DECL_VIRTUAL_P (e->callee->decl) + || (!DECL_COMDAT (e->callee->decl) && !DECL_EXTERNAL (e->callee->decl))) /* Don't reuse if more than one function shares a comdat group. If the other function(s) are needed, we need to emit even this function out of line. */ diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index ec45d7c5271..e1d821e3988 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -2120,6 +2120,7 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, } TREE_TYPE (fndecl) = new_type; + DECL_VIRTUAL_P (fndecl) = 0; if (otypes) VEC_free (tree, heap, otypes); VEC_free (tree, heap, oparms); diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c index 64ccb4ead27..96482f12826 100644 --- a/gcc/ipa-reference.c +++ b/gcc/ipa-reference.c @@ -200,6 +200,8 @@ ipa_reference_get_not_read_global (struct cgraph_node *fn) info = get_reference_optimization_summary (fn); if (info) return info->statics_not_read; + else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF) + return all_module_statics; else return NULL; } @@ -217,6 +219,8 @@ ipa_reference_get_not_written_global (struct cgraph_node *fn) info = get_reference_optimization_summary (fn); if (info) return info->statics_not_written; + else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF) + return all_module_statics; else return NULL; } @@ -299,9 +303,13 @@ propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x for (e = x->callees; e; e = e->next_callee) { struct cgraph_node *y = e->callee; + enum availability avail; + avail = cgraph_function_body_availability (e->callee); /* Only look into nodes we can propagate something. */ - if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE) + if (avail > AVAIL_OVERWRITABLE + || (avail == AVAIL_OVERWRITABLE + && (flags_from_decl_or_type (e->callee->decl) & ECF_LEAF))) { int flags = flags_from_decl_or_type (e->callee->decl); if (get_reference_vars_info (y)) @@ -573,17 +581,28 @@ read_write_all_from_decl (struct cgraph_node *node, bool * read_all, { tree decl = node->decl; int flags = flags_from_decl_or_type (decl); - if (flags & ECF_CONST) + if ((flags & ECF_LEAF) + && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) + ; + else if (flags & ECF_CONST) ; else if ((flags & ECF_PURE) || cgraph_node_cannot_return (node)) - *read_all = true; + { + *read_all = true; + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " %s/%i -> read all\n", + cgraph_node_name (node), node->uid); + } else { /* TODO: To be able to produce sane results, we should also handle common builtins, in particular throw. */ *read_all = true; *write_all = true; + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " %s/%i -> read all, write all\n", + cgraph_node_name (node), node->uid); } } @@ -629,6 +648,11 @@ propagate (void) node_info = get_reference_vars_info (node); gcc_assert (node_info); + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Starting cycle with %s/%i\n", + cgraph_node_name (node), node->uid); + node_l = &node_info->local; node_g = &node_info->global; @@ -647,9 +671,15 @@ propagate (void) if (!(ie->indirect_info->ecf_flags & ECF_CONST)) { read_all = true; + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " indirect call -> read all\n"); if (!cgraph_edge_cannot_lead_to_return (ie) && !(ie->indirect_info->ecf_flags & ECF_PURE)) - write_all = true; + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " indirect call -> write all\n"); + write_all = true; + } } @@ -659,6 +689,9 @@ propagate (void) w = w_info->next_cycle; while (w && (!read_all || !write_all)) { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " Visiting %s/%i\n", + cgraph_node_name (w), w->uid); /* When function is overwrittable, we can not assume anything. */ if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE) read_write_all_from_decl (w, &read_all, &write_all); @@ -671,9 +704,15 @@ propagate (void) if (!(ie->indirect_info->ecf_flags & ECF_CONST)) { read_all = true; + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " indirect call -> read all\n"); if (!cgraph_edge_cannot_lead_to_return (ie) && !(ie->indirect_info->ecf_flags & ECF_PURE)) - write_all = true; + { + write_all = true; + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " indirect call -> write all\n"); + } } w_info = (struct ipa_dfs_info *) w->aux; @@ -841,7 +880,8 @@ propagate (void) continue; node_info = get_reference_vars_info (node); - if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE) + if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE + || (flags_from_decl_or_type (node->decl) & ECF_LEAF)) { node_g = &node_info->global; diff --git a/gcc/ipa.c b/gcc/ipa.c index 8c0ca86d59d..9670a9c7941 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -238,7 +238,12 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) #endif varpool_reset_queue (); for (node = cgraph_nodes; node; node = node->next) - if (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node) + if ((!cgraph_can_remove_if_no_direct_calls_and_refs_p (node) + /* Keep around virtual functions for possible devirtualization. */ + || (!before_inlining_p + && !node->global.inlined_to + && DECL_VIRTUAL_P (node->decl) + && (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl)))) && ((!DECL_EXTERNAL (node->decl)) || before_inlining_p)) { @@ -565,7 +570,6 @@ ipa_discover_readonly_nonaddressable_vars (void) if (dump_file) fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode)); TREE_READONLY (vnode->decl) = 1; - vnode->const_value_known |= varpool_decide_const_value_known (vnode); } } if (dump_file) @@ -617,7 +621,7 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool return true; } } - if (node->local.used_from_object_file) + if (cgraph_used_from_object_file_p (node)) return true; if (DECL_PRESERVE_P (node->decl)) return true; @@ -734,6 +738,7 @@ function_and_variable_visibility (bool whole_program) struct cgraph_node *alias; gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl)); cgraph_make_decl_local (node->decl); + node->resolution = LDPR_PREVAILING_DEF_IRONLY; for (alias = node->same_body; alias; alias = alias->next) cgraph_make_decl_local (alias->decl); if (node->same_comdat_group) @@ -772,9 +777,6 @@ function_and_variable_visibility (bool whole_program) || ! (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl)))))) DECL_COMMON (vnode->decl) = 0; - /* Even extern variables might have initializers known. - See, for example testsuite/g++.dg/opt/static3.C */ - vnode->const_value_known |= varpool_decide_const_value_known (vnode); } for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed) { @@ -797,7 +799,7 @@ function_and_variable_visibility (bool whole_program) In this case we do not sed used_from_object_file. */ || !vnode->finalized)) || DECL_PRESERVE_P (vnode->decl) - || vnode->used_from_object_file + || varpool_used_from_object_file_p (vnode) || pointer_set_contains (aliased_vnodes, vnode) || lookup_attribute ("externally_visible", DECL_ATTRIBUTES (vnode->decl)))) @@ -808,8 +810,8 @@ function_and_variable_visibility (bool whole_program) { gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl)); cgraph_make_decl_local (vnode->decl); + vnode->resolution = LDPR_PREVAILING_DEF_IRONLY; } - vnode->const_value_known |= varpool_decide_const_value_known (vnode); gcc_assert (TREE_STATIC (vnode->decl)); } pointer_set_destroy (aliased_nodes); diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 4685dd4b4f2..f1a1ee1c0fb 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,13 @@ +2010-09-22 Joseph Myers <joseph@codesourcery.com> + + * jvspec.c (lang_specific_driver): Handle OPT__help instead of + OPT_fhelp. + * lang.opt (-CLASSPATH, -all-warnings, -bootclasspath, -classpath, + -dependencies, -encoding, -extdirs, -include-directory, + -include-directory=, -output-class-directory, + -output-class-directory=, -resource, -resource=, + -user-dependencies): New. + 2010-09-16 Richard Guenther <rguenther@suse.de> * jcf-parse.c (current_file_list): Remove. diff --git a/gcc/java/jvspec.c b/gcc/java/jvspec.c index c7f5273dfc8..7fe44f3b23d 100644 --- a/gcc/java/jvspec.c +++ b/gcc/java/jvspec.c @@ -238,7 +238,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, added--; break; - case OPT_fhelp: + case OPT__help: want_spec_file = 0; break; diff --git a/gcc/java/lang.opt b/gcc/java/lang.opt index 7350ccbe08c..8f529787f4d 100644 --- a/gcc/java/lang.opt +++ b/gcc/java/lang.opt @@ -24,6 +24,48 @@ Language Java +-CLASSPATH +Java Separate Alias(fclasspath=) + +-all-warnings +Java Alias(Wall) + +-bootclasspath +Java Separate Alias(fbootclasspath=) + +-classpath +Java Separate Alias(fclasspath=) + +-dependencies +Java Alias(M) + +-encoding +Java Separate Alias(fencoding=) + +-extdirs +Java Separate Alias(fextdirs=) + +-include-directory +Java Separate Alias(I) + +-include-directory= +Java Joined Alias(I) + +-output-class-directory +Java Separate Alias(foutput-class-dir=) + +-output-class-directory= +Java Joined Alias(foutput-class-dir=) + +-resource +Java Separate Alias(fcompile-resource=) + +-resource= +Java Joined Alias(fcompile-resource=) + +-user-dependencies +Java Alias(MM) + C Driver ; Java driver option in fact distinct from C-family option with the same name. diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index c89763bbee0..a4dda6b7bed 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -178,7 +178,6 @@ extern tree lhd_make_node (enum tree_code); #define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL #define LANG_HOOKS_GET_SUBRANGE_BOUNDS NULL #define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE reconstruct_complex_type -#define LANG_HOOKS_HASH_TYPES true #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \ LANG_HOOKS_MAKE_TYPE, \ @@ -195,8 +194,7 @@ extern tree lhd_make_node (enum tree_code); LANG_HOOKS_TYPE_HASH_EQ, \ LANG_HOOKS_GET_ARRAY_DESCR_INFO, \ LANG_HOOKS_GET_SUBRANGE_BOUNDS, \ - LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \ - LANG_HOOKS_HASH_TYPES \ + LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE \ } /* Declaration hooks. */ diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 7a585085ef0..ce7522b1585 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -176,7 +176,7 @@ lhd_set_decl_assembler_name (tree decl) is less than the whole compilation. Concatenate a distinguishing number - we use the DECL_UID. */ - if (TREE_PUBLIC (decl) || DECL_CONTEXT (decl) == NULL_TREE) + if (TREE_PUBLIC (decl) || DECL_FILE_SCOPE_P (decl)) id = targetm.mangle_decl_assembler_name (decl, DECL_NAME (decl)); else { diff --git a/gcc/langhooks.h b/gcc/langhooks.h index 87bac2826d0..eb8b8fcfbd4 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -138,11 +138,6 @@ struct lang_hooks_for_types return values from functions. The argument TYPE is the top of the chain, and BOTTOM is the new type which we will point to. */ tree (*reconstruct_complex_type) (tree, tree); - - /* Nonzero if types that are identical are to be hashed so that only - one copy is kept. If a language requires unique types for each - user-specified type, such as Ada, this should be set to TRUE. */ - bool hash_types; }; /* Language hooks related to decls and the symbol table. */ diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 5410e8fcbc5..b82fa735ded 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -519,6 +519,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, bp_pack_value (&bp, node->finalized_by_frontend, 1); bp_pack_value (&bp, node->frequency, 2); lto_output_bitpack (&bp); + lto_output_uleb128_stream (ob->main_stream, node->resolution); if (node->same_body) { @@ -550,6 +551,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, lto_output_fn_decl_index (ob->decl_state, ob->main_stream, alias->thunk.alias); } + lto_output_uleb128_stream (ob->main_stream, alias->resolution); alias = alias->previous; } while (alias); @@ -578,7 +580,6 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node bp_pack_value (&bp, node->force_output, 1); bp_pack_value (&bp, node->finalized, 1); bp_pack_value (&bp, node->alias, 1); - bp_pack_value (&bp, node->const_value_known, 1); gcc_assert (!node->alias || !node->extra_name); gcc_assert (node->finalized || !node->analyzed); gcc_assert (node->needed); @@ -611,12 +612,16 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node else ref = LCC_NOT_FOUND; lto_output_sleb128_stream (ob->main_stream, ref); + lto_output_uleb128_stream (ob->main_stream, node->resolution); if (count) { lto_output_uleb128_stream (ob->main_stream, count); for (alias = node->extra_name; alias; alias = alias->next) - lto_output_var_decl_index (ob->decl_state, ob->main_stream, alias->decl); + { + lto_output_var_decl_index (ob->decl_state, ob->main_stream, alias->decl); + lto_output_uleb128_stream (ob->main_stream, alias->resolution); + } } } @@ -813,8 +818,7 @@ compute_ltrans_boundary (struct lto_out_decl_state *state, if (DECL_INITIAL (vnode->decl) && !lto_varpool_encoder_encode_initializer_p (varpool_encoder, vnode) - && (DECL_IN_CONSTANT_POOL (vnode->decl) - || TREE_READONLY (vnode->decl))) + && const_value_known_p (vnode->decl)) { lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode); add_references (encoder, varpool_encoder, &vnode->ref_list); @@ -927,7 +931,8 @@ input_overwrite_node (struct lto_file_decl_data *file_data, unsigned int self_time, unsigned int time_inlining_benefit, unsigned int self_size, - unsigned int size_inlining_benefit) + unsigned int size_inlining_benefit, + enum ld_plugin_symbol_resolution resolution) { node->aux = (void *) tag; node->local.inline_summary.estimated_self_stack_size = stack_size; @@ -956,7 +961,16 @@ input_overwrite_node (struct lto_file_decl_data *file_data, node->lowered = bp_unpack_value (bp, 1); node->analyzed = tag == LTO_cgraph_analyzed_node; node->in_other_partition = bp_unpack_value (bp, 1); - if (node->in_other_partition) + if (node->in_other_partition + /* Avoid updating decl when we are seeing just inline clone. + When inlining function that has functions already inlined into it, + we produce clones of inline clones. + + WPA partitioning might put each clone into different unit and + we might end up streaming inline clone from other partition + to support clone we are interested in. */ + && (!node->clone_of + || node->clone_of->decl != node->decl)) { DECL_EXTERNAL (node->decl) = 1; TREE_STATIC (node->decl) = 0; @@ -964,6 +978,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data, node->alias = bp_unpack_value (bp, 1); node->finalized_by_frontend = bp_unpack_value (bp, 1); node->frequency = (enum node_frequency)bp_unpack_value (bp, 2); + node->resolution = resolution; } /* Output the part of the cgraph in SET. */ @@ -1011,6 +1026,7 @@ input_node (struct lto_file_decl_data *file_data, int size_inlining_benefit = 0; unsigned long same_body_count = 0; int clone_ref; + enum ld_plugin_symbol_resolution resolution; clone_ref = lto_input_sleb128 (ib); @@ -1049,9 +1065,10 @@ input_node (struct lto_file_decl_data *file_data, "node %d", node->uid); bp = lto_input_bitpack (ib); + resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib); input_overwrite_node (file_data, node, tag, &bp, stack_size, self_time, time_inlining_benefit, self_size, - size_inlining_benefit); + size_inlining_benefit, resolution); /* Store a reference for now, and fix up later to be a pointer. */ node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref; @@ -1064,6 +1081,7 @@ input_node (struct lto_file_decl_data *file_data, { tree alias_decl; int type; + struct cgraph_node *alias; decl_index = lto_input_uleb128 (ib); alias_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index); type = lto_input_uleb128 (ib); @@ -1072,7 +1090,7 @@ input_node (struct lto_file_decl_data *file_data, tree real_alias; decl_index = lto_input_uleb128 (ib); real_alias = lto_file_decl_data_get_fn_decl (file_data, decl_index); - cgraph_same_body_alias (alias_decl, real_alias); + alias = cgraph_same_body_alias (alias_decl, real_alias); } else { @@ -1081,11 +1099,12 @@ input_node (struct lto_file_decl_data *file_data, tree real_alias; decl_index = lto_input_uleb128 (ib); real_alias = lto_file_decl_data_get_fn_decl (file_data, decl_index); - cgraph_add_thunk (alias_decl, fn_decl, type & 2, fixed_offset, - virtual_value, - (type & 4) ? size_int (virtual_value) : NULL_TREE, - real_alias); + alias = cgraph_add_thunk (alias_decl, fn_decl, type & 2, fixed_offset, + virtual_value, + (type & 4) ? size_int (virtual_value) : NULL_TREE, + real_alias); } + alias->resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib); } return node; } @@ -1115,7 +1134,6 @@ input_varpool_node (struct lto_file_decl_data *file_data, node->force_output = bp_unpack_value (&bp, 1); node->finalized = bp_unpack_value (&bp, 1); node->alias = bp_unpack_value (&bp, 1); - node->const_value_known = bp_unpack_value (&bp, 1); node->analyzed = node->finalized; node->used_from_other_partition = bp_unpack_value (&bp, 1); node->in_other_partition = bp_unpack_value (&bp, 1); @@ -1130,6 +1148,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, ref = lto_input_sleb128 (ib); /* Store a reference for now, and fix up later to be a pointer. */ node->same_comdat_group = (struct varpool_node *) (intptr_t) ref; + node->resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib); if (aliases_p) { count = lto_input_uleb128 (ib); @@ -1137,7 +1156,9 @@ input_varpool_node (struct lto_file_decl_data *file_data, { tree decl = lto_file_decl_data_get_var_decl (file_data, lto_input_uleb128 (ib)); - varpool_extra_name_alias (decl, var_decl); + struct varpool_node *alias; + alias = varpool_extra_name_alias (decl, var_decl); + alias->resolution = (enum ld_plugin_symbol_resolution)lto_input_uleb128 (ib); } } return node; @@ -1283,11 +1304,20 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, len = lto_input_uleb128 (ib); } - + /* AUX pointers should be all non-zero for nodes read from the stream. */ +#ifdef ENABLE_CHECKING + FOR_EACH_VEC_ELT (cgraph_node_ptr, nodes, i, node) + gcc_assert (node->aux); +#endif FOR_EACH_VEC_ELT (cgraph_node_ptr, nodes, i, node) { int ref = (int) (intptr_t) node->global.inlined_to; + /* We share declaration of builtins, so we may read same node twice. */ + if (!node->aux) + continue; + node->aux = NULL; + /* Fixup inlined_to from reference to pointer. */ if (ref != LCC_NOT_FOUND) node->global.inlined_to = VEC_index (cgraph_node_ptr, nodes, ref); @@ -1302,6 +1332,8 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, else node->same_comdat_group = NULL; } + FOR_EACH_VEC_ELT (cgraph_node_ptr, nodes, i, node) + node->aux = (void *)1; return nodes; } @@ -1323,9 +1355,17 @@ input_varpool_1 (struct lto_file_decl_data *file_data, input_varpool_node (file_data, ib)); len--; } +#ifdef ENABLE_CHECKING + FOR_EACH_VEC_ELT (varpool_node_ptr, varpool, i, node) + gcc_assert (!node->aux); +#endif FOR_EACH_VEC_ELT (varpool_node_ptr, varpool, i, node) { int ref = (int) (intptr_t) node->same_comdat_group; + /* We share declaration of builtins, so we may read same node twice. */ + if (node->aux) + continue; + node->aux = (void *)1; /* Fixup same_comdat_group from reference to pointer. */ if (ref != LCC_NOT_FOUND) @@ -1333,6 +1373,8 @@ input_varpool_1 (struct lto_file_decl_data *file_data, else node->same_comdat_group = NULL; } + FOR_EACH_VEC_ELT (varpool_node_ptr, varpool, i, node) + node->aux = NULL; return varpool; } diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 83315e86d1b..c6d3c9bacc1 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -2241,7 +2241,7 @@ lto_input_ts_translation_unit_decl_tree_pointers (struct lto_input_block *ib, struct data_in *data_in, tree expr) { - TRANSLATION_UNIT_LANGUAGE (expr) = input_string (data_in, ib); + TRANSLATION_UNIT_LANGUAGE (expr) = xstrdup (input_string (data_in, ib)); VEC_safe_push (tree, gc, all_translation_units, expr); } diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c index bdfbd7d67a2..1d90ab113f6 100644 --- a/gcc/lto-symtab.c +++ b/gcc/lto-symtab.c @@ -51,6 +51,8 @@ struct GTY(()) lto_symtab_entry_def /* LTO file-data and symbol resolution for this decl. */ struct lto_file_decl_data * GTY((skip (""))) file_data; enum ld_plugin_symbol_resolution resolution; + /* True when resolution was guessed and not read from the file. */ + bool guessed; /* Pointer to the next entry with the same key. Before decl merging this links all symbols from the different TUs. After decl merging this links merged but incompatible decls, thus all prevailing ones @@ -513,12 +515,14 @@ lto_symtab_resolve_symbols (void **slot) if (!lto_symtab_resolve_can_prevail_p (e)) { e->resolution = LDPR_RESOLVED_IR; + e->guessed = true; continue; } /* Set a default resolution - the final prevailing one will get adjusted later. */ e->resolution = LDPR_PREEMPTED_IR; + e->guessed = true; if (!lto_symtab_resolve_replaceable_p (e)) { if (prevailing) @@ -572,6 +576,7 @@ found: resolution file. These variables still need manual externally_visible attribute. */ prevailing->resolution = LDPR_PREVAILING_DEF_IRONLY; + prevailing->guessed = true; } /* Merge all decls in the symbol table chain to the prevailing decl and @@ -740,27 +745,21 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED) && TREE_CODE (prevailing->decl) != VAR_DECL) prevailing->next = NULL; - /* Set used_from_object_file flags. */ - if (prevailing->resolution == LDPR_PREVAILING_DEF - || prevailing->resolution == LDPR_PREEMPTED_REG - || prevailing->resolution == LDPR_RESOLVED_EXEC - || prevailing->resolution == LDPR_RESOLVED_DYN) - { - if (TREE_CODE (prevailing->decl) == FUNCTION_DECL) - { - if (prevailing->node->same_body_alias) - prevailing->node->same_body->local.used_from_object_file = true; - else - prevailing->node->local.used_from_object_file = true; - } - else - { - if (prevailing->vnode->alias) - prevailing->vnode->extra_name->used_from_object_file = true; - else - prevailing->vnode->used_from_object_file = true; - } - } + /* Store resolution decision into the callgraph. + In LTRANS don't overwrite information we stored into callgraph at + WPA stage. + + Do not bother to store guessed decisions. Generic code knows how + to handle UNKNOWN relocation well. + + The problem with storing guessed decision is whether to use + PREVAILING_DEF or PREVAILING_DEF_IRONLY. First one would disable + some whole program optimizations, while ther second would imply + to many whole program assumptions. */ + if (prevailing->node && !flag_ltrans && !prevailing->guessed) + prevailing->node->resolution = prevailing->resolution; + else if (prevailing->vnode && !flag_ltrans && !prevailing->guessed) + prevailing->vnode->resolution = prevailing->resolution; return 1; } diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index 0ef8b8729ae..540101773ef 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -423,7 +423,6 @@ run_gcc (unsigned argc, char *argv[]) argv_ptr[0] = linker_output; argv_ptr[1] = "-o"; argv_ptr[2] = flto_out; - argv_ptr[3] = "-combine"; } else if (lto_mode == LTO_MODE_WHOPR) { @@ -459,15 +458,14 @@ run_gcc (unsigned argc, char *argv[]) strcpy (tmp, ltrans_output_file); argv_ptr[2] = "-fwpa"; - argv_ptr[3] = "-combine"; } else fatal ("invalid LTO mode"); /* Append the input objects and possible preceeding arguments. */ for (i = 1; i < argc; ++i) - argv_ptr[3 + i] = argv[i]; - argv_ptr[3 + i] = NULL; + argv_ptr[2 + i] = argv[i]; + argv_ptr[2 + i] = NULL; fork_execute (CONST_CAST (char **, new_argv)); diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 5e4955b80c7..7aa054ce2a2 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,35 @@ +2010-09-25 Jie Zhang <jie@codesourcery.com> + + * lto.c (lto_read_all_file_options): Start a new line after + printing out file names. + +2010-09-24 Jan Hubicka <jh@suse.cz> + + * lto.c (lto_promote_cross_file_statics): Use const_value_known_p. + +2010-09-20 Jan Hubicka <jh@suse.cz> + + PR tree-optimize/45605 + * lto.c (lto_promote_cross_file_statics): Use const_value_known_p. + +2010-09-18 Gerald Pfeifer <gerald@pfeifer.com> + + * lto-elf.c (lto_obj_file_open): Also provide filename when + elf_begin fails. + +2010-09-17 Jan Hubicka <jh@suse.cz> + + * lto.c (lto_promote_cross_file_statics): Use const_value_known. + +2010-09-17 Richard Guenther <rguenther@suse.de> + + * lang.opt (flag_wpa): Also enable for the driver. + +2010-09-16 Jan Hubicka <jh@suse.cz> + + * lto.c (lto_materialize_function): Do not tamper with STATIC and + EXTERNAL flags. + 2010-09-15 Laurynas Biveinis <laurynas.biveinis@gmail.com> * lto-tree.h (struct lang_type): Add variable_size GTY option. diff --git a/gcc/lto/lang.opt b/gcc/lto/lang.opt index 53ab8e80830..199adeaf4e0 100644 --- a/gcc/lto/lang.opt +++ b/gcc/lto/lang.opt @@ -33,7 +33,7 @@ LTO Joined Var(ltrans_output_list) Specify a file to which a list of files output by LTRANS is written. fwpa -LTO Report Var(flag_wpa) Optimization +LTO Driver Report Var(flag_wpa) Optimization Run the link-time optimizer in whole program analysis (WPA) mode. fresolution= diff --git a/gcc/lto/lto-elf.c b/gcc/lto/lto-elf.c index 0d4f1067be5..53cc0570bc3 100644 --- a/gcc/lto/lto-elf.c +++ b/gcc/lto/lto-elf.c @@ -674,7 +674,7 @@ lto_obj_file_open (const char *filename, bool writable) NULL); if (!elf_file->elf) { - error ("could not open ELF file: %s", elf_errmsg (0)); + error ("could not open %s as an ELF file: %s", fname, elf_errmsg (0)); goto fail; } diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 74782133440..e2fa97576eb 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -160,9 +160,6 @@ lto_materialize_function (struct cgraph_node *node) and also functions that are needed to produce virtual clones. */ if (node->analyzed || has_analyzed_clone_p (node)) { - /* This function has a definition. */ - TREE_STATIC (decl) = 1; - /* Clones don't need to be read. */ if (node->clone_of) return; @@ -198,8 +195,6 @@ lto_materialize_function (struct cgraph_node *node) if (!flag_wpa) ggc_collect (); } - else - DECL_EXTERNAL (decl) = 1; /* Let the middle end know about the function. */ rest_of_decl_compilation (decl, 1, 0); @@ -1013,7 +1008,7 @@ lto_promote_cross_file_statics (void) from this partition that are not in this partition. This needs to be done recursively. */ for (vnode = varpool_nodes; vnode; vnode = vnode->next) - if ((TREE_READONLY (vnode->decl) || DECL_IN_CONSTANT_POOL (vnode->decl)) + if (const_value_known_p (vnode->decl) && DECL_INITIAL (vnode->decl) && !varpool_node_in_set_p (vnode, vset) && referenced_from_this_partition_p (&vnode->ref_list, set, vset) @@ -1053,7 +1048,8 @@ lto_promote_cross_file_statics (void) && !v->externally_visible && v->analyzed) { if (promote_var (v) - && DECL_INITIAL (v->decl) && TREE_READONLY (v->decl) + && DECL_INITIAL (v->decl) + && const_value_known_p (v->decl) && !pointer_set_insert (inserted, vnode)) VEC_safe_push (varpool_node_ptr, heap, promoted_initializers, v); @@ -1693,6 +1689,9 @@ lto_read_all_file_options (void) free (file_data); } + if (!quiet_flag) + fprintf (stderr, "\n"); + /* Apply globally the options read from all the files. */ lto_reissue_options (); } diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 132679ba132..29417d9650e 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,22 @@ +2010-09-26 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc-act.c: Removed historical, obsolete comment at the top of + the file. + +2010-09-21 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/23710 + * objc-act.c (objc_start_method_definition): Do not abort upon a + 'method definition not in @implementation context' error. Return + 'false' instead. + +2010-09-21 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/25965 + * objc-act.c (objc_get_interface_ivars): New function. + (objc_collecting_ivars): New variable. + (continue_class): Set and reset objc_collecting_ivars for context. + 2010-09-15 Nicola Pero <nicola.pero@meta-innovation.com> Merge from 'apple/trunk' branch on FSF servers. diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index d8fbe368a78..e98890629c2 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -20,26 +20,6 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ - -/* Purpose: This module implements the Objective-C 4.0 language. - - compatibility issues (with the Stepstone translator): - - - does not recognize the following 3.3 constructs. - @requires, @classes, @messages, = (...) - - methods with variable arguments must conform to ANSI standard. - - tagged structure definitions that appear in BOTH the interface - and implementation are not allowed. - - public/private: all instance variables are public within the - context of the implementation...I consider this to be a bug in - the translator. - - statically allocated objects are not supported. the user will - receive an error if this service is requested. - - code generation `options': - - */ - #include "config.h" #include "system.h" #include "coretypes.h" @@ -371,6 +351,8 @@ int objc_public_flag; /* Use to generate method labels. */ static int method_slot = 0; +static int objc_collecting_ivars = 0; + #define BUFSIZE 1024 static char *errbuf; /* Buffer for error diagnostics */ @@ -775,18 +757,30 @@ void objc_add_method_declaration (tree decl) { if (!objc_interface_context) - fatal_error ("method declaration not in @interface context"); + { + /* PS: At the moment, due to how the parser works, it should be + impossible to get here. But it's good to have the check in + case the parser changes. + */ + fatal_error ("method declaration not in @interface context"); + } objc_add_method (objc_interface_context, decl, objc_inherit_code == CLASS_METHOD_DECL); } -void +/* Return 'true' if the method definition could be started, and + 'false' if not (because we are outside an @implementation context). +*/ +bool objc_start_method_definition (tree decl) { if (!objc_implementation_context) - fatal_error ("method definition not in @implementation context"); + { + error ("method definition not in @implementation context"); + return false; + } #ifndef OBJCPLUS /* Indicate no valid break/continue context by setting these variables @@ -799,6 +793,7 @@ objc_start_method_definition (tree decl) decl, objc_inherit_code == CLASS_METHOD_DECL); start_method_def (decl); + return true; } void @@ -3453,6 +3448,21 @@ objc_get_class_ivars (tree class_name) return error_mark_node; } +/* Called when checking the variables in a struct. If we are not + doing the ivars list inside an @interface context, then returns + fieldlist unchanged. Else, returns the list of class ivars. +*/ +tree +objc_get_interface_ivars (tree fieldlist) +{ + if (!objc_collecting_ivars || !objc_interface_context + || TREE_CODE (objc_interface_context) != CLASS_INTERFACE_TYPE + || CLASS_SUPER_NAME (objc_interface_context) == NULL_TREE) + return fieldlist; + + return get_class_ivars (objc_interface_context, true); +} + /* Used by: build_private_template, continue_class, and for @defs constructs. */ @@ -7714,7 +7724,9 @@ continue_class (tree klass) push_lang_context (lang_name_c); #endif /* OBJCPLUS */ + objc_collecting_ivars = 1; build_private_template (klass); + objc_collecting_ivars = 0; #ifdef OBJCPLUS pop_lang_context (); diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog index 109d2327ed6..e7fe12bcf0b 100644 --- a/gcc/objcp/ChangeLog +++ b/gcc/objcp/ChangeLog @@ -1,3 +1,9 @@ +2010-09-21 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/25965 + * objcp-decl.c (objcp_finish_struct): Call + objc_get_interface_ivars() and check for duplicate ivars. + 2010-06-28 Steven Bosscher <steven@gcc.gnu.org> * objcp-lang.c: Do not include except.h. diff --git a/gcc/objcp/objcp-decl.c b/gcc/objcp/objcp-decl.c index 8c688761098..af19a053823 100644 --- a/gcc/objcp/objcp-decl.c +++ b/gcc/objcp/objcp-decl.c @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "cp-tree.h" +#include "hashtab.h" #include "objc-act.h" #include "objcp-decl.h" @@ -63,6 +64,39 @@ objcp_finish_struct (location_t loc ATTRIBUTE_UNUSED, finish_member_declaration (field); } t = finish_struct (t, attributes); + + /* If we are inside an @interface and are generating the list of + ivars, we need to check for duplicate ivars. + */ + if (fieldlist) + { + tree original_fieldlist = fieldlist; + fieldlist = objc_get_interface_ivars (fieldlist); + if (fieldlist != original_fieldlist) + { + /* Minimal implementation of the equivalent of the C + front-end's detect_field_duplicates(). + */ + htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL); + tree x, y; + void **slot; + + for (x = fieldlist; x ; x = DECL_CHAIN (x)) + if ((y = DECL_NAME (x)) != 0) + { + slot = htab_find_slot (htab, y, INSERT); + if (*slot) + { + error ("duplicate member %q+D", x); + DECL_NAME (x) = NULL_TREE; + } + *slot = y; + } + + htab_delete (htab); + } + } + pop_lang_context (); return t; diff --git a/gcc/optc-gen.awk b/gcc/optc-gen.awk index bee780c0b63..4a146dddffb 100644 --- a/gcc/optc-gen.awk +++ b/gcc/optc-gen.awk @@ -30,6 +30,7 @@ BEGIN { n_opts = 0 n_langs = 0 n_target_save = 0 + n_extra_vars = 0 quote = "\042" comma = "," FS=SUBSEP @@ -48,6 +49,10 @@ BEGIN { target_save_decl[n_target_save] = $2 n_target_save++ } + else if ($1 == "Variable") { + extra_vars[n_extra_vars] = $2 + n_extra_vars++ + } else { name = opt_args("Mask", $1) if (name == "") { @@ -72,7 +77,6 @@ print "#include " quote "opts.h" quote print "#include " quote "intl.h" quote print "" print "#ifdef GCC_DRIVER" -print "int target_flags;" print "int target_flags_explicit;" print "#else" print "#include " quote "flags.h" quote @@ -81,6 +85,9 @@ print "#endif /* GCC_DRIVER */" print "" have_save = 0; +for (i = 0; i < n_extra_vars; i++) { + print extra_vars[i] ";" +} for (i = 0; i < n_opts; i++) { if (flag_set_p("Save", flags[i])) have_save = 1; @@ -90,11 +97,7 @@ for (i = 0; i < n_opts; i++) { continue; if (flag_set_p("VarExists", flags[i])) { - # Need it for the gcc driver. - if (name in var_seen) - continue; - init = "" - gcc_driver = 1 + continue; } else { init = opt_args("Init", flags[i]) @@ -102,16 +105,11 @@ for (i = 0; i < n_opts; i++) { init = " = " init; else if (name in var_seen) continue; - gcc_driver = 0 } - if (gcc_driver == 1) - print "#ifdef GCC_DRIVER" print "/* Set by -" opts[i] "." print " " help[i] " */" print var_type(flags[i]) name init ";" - if (gcc_driver == 1) - print "#endif /* GCC_DRIVER */" print "" var_seen[name] = 1; diff --git a/gcc/opth-gen.awk b/gcc/opth-gen.awk index 0d1d0df375a..423328ddfdb 100644 --- a/gcc/opth-gen.awk +++ b/gcc/opth-gen.awk @@ -28,6 +28,7 @@ BEGIN { n_opts = 0 n_langs = 0 n_target_save = 0 + n_extra_vars = 0 n_extra_masks = 0 FS=SUBSEP } @@ -43,6 +44,10 @@ BEGIN { target_save_decl[n_target_save] = $2 n_target_save++ } + else if ($1 == "Variable") { + extra_vars[n_extra_vars] = $2 + n_extra_vars++ + } else { name = opt_args("Mask", $1) if (name == "") { @@ -65,12 +70,17 @@ print "" print "#ifndef OPTIONS_H" print "#define OPTIONS_H" print "" -print "extern int target_flags;" print "extern int target_flags_explicit;" print "" have_save = 0; +for (i = 0; i < n_extra_vars; i++) { + var = extra_vars[i] + sub(" *=.*", "", var) + print "extern " var ";" +} + for (i = 0; i < n_opts; i++) { if (flag_set_p("Save", flags[i])) have_save = 1; diff --git a/gcc/opts-common.c b/gcc/opts-common.c index 8299edd4ab9..078610fdb57 100644 --- a/gcc/opts-common.c +++ b/gcc/opts-common.c @@ -24,7 +24,10 @@ along with GCC; see the file COPYING3. If not see #include "opts.h" #include "options.h" #include "diagnostic.h" -#include "tm.h" /* For SWITCH_TAKES_ARG and WORD_SWITCH_TAKES_ARG. */ +#include "tm.h" /* For SWITCH_TAKES_ARG, WORD_SWITCH_TAKES_ARG and + TARGET_OPTION_TRANSLATE_TABLE. */ + +static void prune_options (struct cl_decoded_option **, unsigned int *); /* Perform a binary search to find which option the command-line INPUT matches. Returns its index in the option array, and @@ -53,7 +56,7 @@ along with GCC; see the file COPYING3. If not see size_t find_opt (const char *input, int lang_mask) { - size_t mn, mx, md, opt_len; + size_t mn, mn_orig, mx, md, opt_len; size_t match_wrong_lang; int comp; @@ -74,6 +77,8 @@ find_opt (const char *input, int lang_mask) mn = md; } + mn_orig = mn; + /* This is the switch that is the best match but for a different front end, or OPT_SPECIAL_unknown if there is no match at all. */ match_wrong_lang = OPT_SPECIAL_unknown; @@ -106,6 +111,40 @@ find_opt (const char *input, int lang_mask) } while (mn != cl_options_count); + if (match_wrong_lang == OPT_SPECIAL_unknown && input[0] == '-') + { + /* Long options, starting "--", may be abbreviated if the + abbreviation is unambiguous. This only applies to options + not taking a joined argument, and abbreviations of "--option" + are permitted even if there is a variant "--option=". */ + size_t mnc = mn_orig + 1; + size_t cmp_len = strlen (input); + while (mnc < cl_options_count + && strncmp (input, cl_options[mnc].opt_text + 1, cmp_len) == 0) + { + /* Option matching this abbreviation. OK if it is the first + match and that does not take a joined argument, or the + second match, taking a joined argument and with only '=' + added to the first match; otherwise considered + ambiguous. */ + if (mnc == mn_orig + 1 + && !(cl_options[mnc].flags & CL_JOINED)) + match_wrong_lang = mnc; + else if (mnc == mn_orig + 2 + && match_wrong_lang == mn_orig + 1 + && (cl_options[mnc].flags & CL_JOINED) + && (cl_options[mnc].opt_len + == cl_options[mn_orig + 1].opt_len + 1) + && strncmp (cl_options[mnc].opt_text + 1, + cl_options[mn_orig + 1].opt_text + 1, + cl_options[mn_orig + 1].opt_len) == 0) + ; /* OK, as long as there are no more matches. */ + else + return OPT_SPECIAL_unknown; + mnc++; + } + } + /* Return the best wrong match, or OPT_SPECIAL_unknown if none. */ return match_wrong_lang; } @@ -197,6 +236,46 @@ generate_canonical_option (size_t opt_index, const char *arg, int value, } } +/* Structure describing mappings from options on the command line to + options to look up with find_opt. */ +struct option_map +{ + /* Prefix of the option on the command line. */ + const char *opt0; + /* If two argv elements are considered to be merged into one option, + prefix for the second element, otherwise NULL. */ + const char *opt1; + /* The new prefix to map to. */ + const char *new_prefix; + /* Whether at least one character is needed following opt1 or opt0 + for this mapping to be used. (--optimize= is valid for -O, but + --warn- is not valid for -W.) */ + bool another_char_needed; + /* Whether the original option is a negated form of the option + resulting from this map. */ + bool negated; +}; +static const struct option_map option_map[] = + { + { "-Wno-", NULL, "-W", false, true }, + { "-fno-", NULL, "-f", false, true }, + { "-mno-", NULL, "-m", false, true }, + { "--debug=", NULL, "-g", false, false }, + { "--machine-", NULL, "-m", true, false }, + { "--machine-no-", NULL, "-m", false, true }, + { "--machine=", NULL, "-m", false, false }, + { "--machine=no-", NULL, "-m", false, true }, + { "--machine", "", "-m", false, false }, + { "--machine", "no-", "-m", false, true }, + { "--optimize=", NULL, "-O", false, false }, + { "--std=", NULL, "-std=", false, false }, + { "--std", "", "-std=", false, false }, + { "--warn-", NULL, "-W", true, false }, + { "--warn-no-", NULL, "-W", false, true }, + { "--", NULL, "-f", true, false }, + { "--no-", NULL, "-f", false, true } + }; + /* Decode the switch beginning at ARGV for the language indicated by LANG_MASK (including CL_COMMON and CL_TARGET if applicable), into the structure *DECODED. Returns the number of switches @@ -207,10 +286,10 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, struct cl_decoded_option *decoded) { size_t opt_index; - const char *opt, *arg = 0; - char *dup = 0; + const char *arg = 0; int value = 1; - unsigned int result = 1, i; + unsigned int result = 1, i, extra_args; + int adjust_len = 0; size_t total_len; char *p; const struct cl_option *option; @@ -220,28 +299,50 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, bool joined_arg_flag; bool have_separate_arg = false; - opt = argv[0]; + extra_args = 0; - opt_index = find_opt (opt + 1, lang_mask); - if (opt_index == OPT_SPECIAL_unknown - && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm') - && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') + opt_index = find_opt (argv[0] + 1, lang_mask); + i = 0; + while (opt_index == OPT_SPECIAL_unknown + && i < ARRAY_SIZE (option_map)) { - /* Drop the "no-" from negative switches. */ - size_t len = strlen (opt) - 3; - - dup = XNEWVEC (char, len + 1); - dup[0] = '-'; - dup[1] = opt[1]; - memcpy (dup + 2, opt + 5, len - 2 + 1); - opt = dup; - value = 0; - opt_index = find_opt (opt + 1, lang_mask); + const char *opt0 = option_map[i].opt0; + const char *opt1 = option_map[i].opt1; + const char *new_prefix = option_map[i].new_prefix; + bool another_char_needed = option_map[i].another_char_needed; + size_t opt0_len = strlen (opt0); + size_t opt1_len = (opt1 == NULL ? 0 : strlen (opt1)); + size_t optn_len = (opt1 == NULL ? opt0_len : opt1_len); + size_t new_prefix_len = strlen (new_prefix); + + extra_args = (opt1 == NULL ? 0 : 1); + value = !option_map[i].negated; + + if (strncmp (argv[0], opt0, opt0_len) == 0 + && (opt1 == NULL + || (argv[1] != NULL && strncmp (argv[1], opt1, opt1_len) == 0)) + && (!another_char_needed + || argv[extra_args][optn_len] != 0)) + { + size_t arglen = strlen (argv[extra_args]); + char *dup; + + adjust_len = (int) optn_len - (int) new_prefix_len; + dup = XNEWVEC (char, arglen + 1 - adjust_len); + memcpy (dup, new_prefix, new_prefix_len); + memcpy (dup + new_prefix_len, argv[extra_args] + optn_len, + arglen - optn_len + 1); + opt_index = find_opt (dup + 1, lang_mask); + free (dup); + } + i++; } if (opt_index == OPT_SPECIAL_unknown) { arg = argv[0]; + extra_args = 0; + value = 1; goto done; } @@ -257,6 +358,7 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, goto done; } + result = extra_args + 1; warn_message = option->warn_message; /* Check to see if the option is disabled for this configuration. */ @@ -276,18 +378,16 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, /* Have arg point to the original switch. This is because some code, such as disable_builtin_function, expects its argument to be persistent until the program exits. */ - arg = argv[0] + cl_options[opt_index].opt_len + 1; - if (!value) - arg += strlen ("no-"); + arg = argv[extra_args] + cl_options[opt_index].opt_len + 1 + adjust_len; if (*arg == '\0' && !(option->flags & CL_MISSING_OK)) { if (separate_arg_flag) { - arg = argv[1]; - result = 2; + arg = argv[extra_args + 1]; + result = extra_args + 2; if (arg == NULL) - result = 1; + result = extra_args + 1; else have_separate_arg = true; } @@ -298,10 +398,10 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, } else if (separate_arg_flag) { - arg = argv[1]; - result = 2; + arg = argv[extra_args + 1]; + result = extra_args + 2; if (arg == NULL) - result = 1; + result = extra_args + 1; else have_separate_arg = true; } @@ -329,7 +429,8 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, const struct cl_option *new_option = &cl_options[new_opt_index]; /* The new option must not be an alias itself. */ - gcc_assert (new_option->alias_target == N_OPTS); + gcc_assert (new_option->alias_target == N_OPTS + || (new_option->flags & CL_SEPARATE_ALIAS)); if (option->neg_alias_arg) { @@ -363,7 +464,11 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, if (!(errors & CL_ERR_MISSING_ARG)) { if (separate_arg_flag || joined_arg_flag) - gcc_assert (arg != NULL); + { + if ((option->flags & CL_MISSING_OK) && arg == NULL) + arg = ""; + gcc_assert (arg != NULL); + } else gcc_assert (arg == NULL); } @@ -392,8 +497,6 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, } done: - if (dup) - free (dup); decoded->opt_index = opt_index; decoded->arg = arg; decoded->value = value; @@ -455,6 +558,17 @@ decode_cmdline_option (const char **argv, unsigned int lang_mask, return result; } +#ifdef TARGET_OPTION_TRANSLATE_TABLE +static const struct { + const char *const option_found; + const char *const replacements; +} target_option_translations[] = +{ + TARGET_OPTION_TRANSLATE_TABLE, + { 0, 0 } +}; +#endif + /* Decode command-line options (ARGC and ARGV being the arguments of main) into an array, setting *DECODED_OPTIONS to a pointer to that array and *DECODED_OPTIONS_COUNT to the number of entries in the @@ -470,9 +584,10 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv, struct cl_decoded_option **decoded_options, unsigned int *decoded_options_count) { - unsigned int n, i; + unsigned int n, i, target_translate_from; struct cl_decoded_option *opt_array; unsigned int num_decoded_options; + bool argv_copied = false; opt_array = XNEWVEC (struct cl_decoded_option, argc); @@ -489,6 +604,7 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv, opt_array[0].errors = 0; num_decoded_options = 1; + target_translate_from = 1; for (i = 1; i < argc; i += n) { const char *opt = argv[i]; @@ -502,15 +618,91 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv, continue; } + if (i >= target_translate_from && (lang_mask & CL_DRIVER)) + { +#ifdef TARGET_OPTION_TRANSLATE_TABLE + int tott_idx; + + for (tott_idx = 0; + target_option_translations[tott_idx].option_found; + tott_idx++) + { + if (strcmp (target_option_translations[tott_idx].option_found, + argv[i]) == 0) + { + unsigned int spaces = 0; + unsigned int m = 0; + const char *sp; + char *np; + + for (sp = target_option_translations[tott_idx].replacements; + *sp; sp++) + { + if (*sp == ' ') + { + spaces++; + while (*sp == ' ') + sp++; + sp--; + } + } + + if (spaces) + { + int new_argc = argc + spaces; + if (argv_copied) + argv = XRESIZEVEC (const char *, argv, new_argc + 1); + else + { + const char **new_argv = XNEWVEC (const char *, + new_argc + 1); + memcpy (new_argv, argv, + (argc + 1) * sizeof (const char *)); + argv = new_argv; + argv_copied = true; + } + memmove (&argv[i] + spaces, &argv[i], + (argc + 1 - i) * sizeof (const char *)); + argc = new_argc; + opt_array = XRESIZEVEC (struct cl_decoded_option, + opt_array, argc); + } + + sp = target_option_translations[tott_idx].replacements; + np = xstrdup (sp); + + while (1) + { + while (*np == ' ') + np++; + if (*np == 0) + break; + argv[i + m++] = np; + while (*np != ' ' && *np) + np++; + if (*np == 0) + break; + *np++ = 0; + } + + target_translate_from = i + m; + gcc_assert (m == spaces + 1); + break; + } + } +#endif + } + n = decode_cmdline_option (argv + i, lang_mask, &opt_array[num_decoded_options]); num_decoded_options++; } - opt_array = XRESIZEVEC (struct cl_decoded_option, opt_array, - num_decoded_options); + if (argv_copied) + free (argv); *decoded_options = opt_array; *decoded_options_count = num_decoded_options; + prune_options (decoded_options, decoded_options_count); } /* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the @@ -533,119 +725,77 @@ cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx) /* Filter out options canceled by the ones after them. */ -void -prune_options (int *argcp, char ***argvp) +static void +prune_options (struct cl_decoded_option **decoded_options, + unsigned int *decoded_options_count) { - int argc = *argcp; - int *options = XNEWVEC (int, argc); - /* We will only return this replacement argv if we remove at least - one argument, so it does not need to be size (argc + 1) to - make room for the terminating NULL because we will always have - freed up at least one slot when we end up using it at all. */ - char **argv = XNEWVEC (char *, argc); - int i, arg_count, need_prune = 0; + unsigned int old_decoded_options_count = *decoded_options_count; + struct cl_decoded_option *old_decoded_options = *decoded_options; + unsigned int new_decoded_options_count; + struct cl_decoded_option *new_decoded_options + = XNEWVEC (struct cl_decoded_option, old_decoded_options_count); + unsigned int i; const struct cl_option *option; - size_t opt_index; - - /* Scan all arguments. */ - for (i = 1; i < argc; i++) - { - int value = 1; - const char *opt = (*argvp) [i]; - - opt_index = find_opt (opt + 1, -1); - if (opt_index == OPT_SPECIAL_unknown - && (opt[1] == 'W' || opt[1] == 'f' || opt[1] == 'm') - && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') - { - char *dup; - - /* Drop the "no-" from negative switches. */ - size_t len = strlen (opt) - 3; - - dup = XNEWVEC (char, len + 1); - dup[0] = '-'; - dup[1] = opt[1]; - memcpy (dup + 2, opt + 5, len - 2 + 1); - opt = dup; - value = 0; - opt_index = find_opt (opt + 1, -1); - free (dup); - } - - if (opt_index == OPT_SPECIAL_unknown) - { -cont: - options [i] = 0; - continue; - } - - option = &cl_options[opt_index]; - if (option->neg_index < 0) - goto cont; - - /* Skip joined switches. */ - if ((option->flags & CL_JOINED)) - goto cont; - - /* Reject negative form of switches that don't take negatives as - unrecognized. */ - if (!value && (option->flags & CL_REJECT_NEGATIVE)) - goto cont; - - options [i] = (int) opt_index; - need_prune |= options [i]; - } - - if (!need_prune) - goto done; /* Remove arguments which are negated by others after them. */ - argv [0] = (*argvp) [0]; - arg_count = 1; - for (i = 1; i < argc; i++) + new_decoded_options_count = 0; + for (i = 0; i < old_decoded_options_count; i++) { - int j, opt_idx; + unsigned int j, opt_idx, next_opt_idx; - opt_idx = options [i]; - if (opt_idx) + if (old_decoded_options[i].errors & ~CL_ERR_WRONG_LANG) + goto keep; + + opt_idx = old_decoded_options[i].opt_index; + switch (opt_idx) { - int next_opt_idx; - for (j = i + 1; j < argc; j++) + case OPT_SPECIAL_unknown: + case OPT_SPECIAL_ignore: + case OPT_SPECIAL_program_name: + case OPT_SPECIAL_input_file: + goto keep; + + default: + gcc_assert (opt_idx < cl_options_count); + option = &cl_options[opt_idx]; + if (option->neg_index < 0) + goto keep; + + /* Skip joined switches. */ + if ((option->flags & CL_JOINED)) + goto keep; + + for (j = i + 1; j < old_decoded_options_count; j++) { - next_opt_idx = options [j]; - if (next_opt_idx - && cancel_option (opt_idx, next_opt_idx, - next_opt_idx)) + if (old_decoded_options[j].errors & ~CL_ERR_WRONG_LANG) + continue; + next_opt_idx = old_decoded_options[j].opt_index; + if (next_opt_idx >= cl_options_count) + continue; + if (cl_options[next_opt_idx].neg_index < 0) + continue; + if ((cl_options[next_opt_idx].flags & CL_JOINED)) + continue; + if (cancel_option (opt_idx, next_opt_idx, next_opt_idx)) break; } - } - else - goto keep; - - if (j == argc) - { + if (j == old_decoded_options_count) + { keep: - argv [arg_count] = (*argvp) [i]; - arg_count++; + new_decoded_options[new_decoded_options_count] + = old_decoded_options[i]; + new_decoded_options_count++; + } + break; } } - if (arg_count != argc) - { - *argcp = arg_count; - *argvp = argv; - /* Add NULL-termination. Guaranteed not to overflow because - arg_count here can only be less than argc. */ - argv[arg_count] = 0; - } - else - { -done: - free (argv); - } - - free (options); + free (old_decoded_options); + new_decoded_options = XRESIZEVEC (struct cl_decoded_option, + new_decoded_options, + new_decoded_options_count); + *decoded_options = new_decoded_options; + *decoded_options_count = new_decoded_options_count; } /* Handle option DECODED for the language indicated by LANG_MASK, diff --git a/gcc/opts.c b/gcc/opts.c index 49c91a4a094..643f88999d5 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1429,7 +1429,6 @@ common_handle_option (const struct cl_decoded_option *decoded, verbose = true; break; - case OPT_fhelp: case OPT__help: { unsigned int all_langs_mask = (1U << cl_lang_count) - 1; @@ -1451,7 +1450,6 @@ common_handle_option (const struct cl_decoded_option *decoded, break; } - case OPT_ftarget_help: case OPT__target_help: print_specific_help (CL_TARGET, CL_UNDOCUMENTED, 0); exit_after_options = true; @@ -1461,7 +1459,6 @@ common_handle_option (const struct cl_decoded_option *decoded, targetm.help (); break; - case OPT_fhelp_: case OPT__help_: { const char * a = arg; @@ -1580,7 +1577,6 @@ common_handle_option (const struct cl_decoded_option *decoded, break; } - case OPT_fversion: case OPT__version: exit_after_options = true; break; diff --git a/gcc/opts.h b/gcc/opts.h index ed175e5de4a..c4d253ff04a 100644 --- a/gcc/opts.h +++ b/gcc/opts.h @@ -206,7 +206,6 @@ extern void decode_cmdline_options_to_array (unsigned int argc, unsigned int lang_mask, struct cl_decoded_option **decoded_options, unsigned int *decoded_options_count); -extern void prune_options (int *argcp, char ***argvp); extern void decode_options (unsigned int argc, const char **argv, struct cl_decoded_option **decoded_options, unsigned int *decoded_options_count); diff --git a/gcc/passes.c b/gcc/passes.c index 47d6471c192..24bae5fcaf3 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -758,7 +758,6 @@ init_optimization_passes (void) struct opt_pass **p = &pass_early_local_passes.pass.sub; NEXT_PASS (pass_fixup_cfg); NEXT_PASS (pass_tree_profile); - NEXT_PASS (pass_cleanup_cfg); NEXT_PASS (pass_init_datastructures); NEXT_PASS (pass_expand_omp); @@ -837,7 +836,6 @@ init_optimization_passes (void) /* Initial scalar cleanups before alias computation. They ensure memory accesses are not indirect wherever possible. */ NEXT_PASS (pass_strip_predict_hints); - NEXT_PASS (pass_update_address_taken); NEXT_PASS (pass_rename_ssa_copies); NEXT_PASS (pass_complete_unrolli); NEXT_PASS (pass_ccp); @@ -1208,15 +1206,13 @@ execute_function_todo (void *data) cfun->last_verified &= ~TODO_verify_ssa; } - if (flags & TODO_update_address_taken) - execute_update_addresses_taken (true); - if (flags & TODO_rebuild_alias) { - if (!(flags & TODO_update_address_taken)) - execute_update_addresses_taken (true); + execute_update_addresses_taken (); compute_may_aliases (); } + else if (optimize && (flags & TODO_update_address_taken)) + execute_update_addresses_taken (); if (flags & TODO_remove_unused_locals) remove_unused_locals (); diff --git a/gcc/postreload.c b/gcc/postreload.c index dbc11bb1874..0a70b2031a5 100644 --- a/gcc/postreload.c +++ b/gcc/postreload.c @@ -2104,15 +2104,17 @@ move2add_note_store (rtx dst, const_rtx set, void *data) && (MODES_OK_FOR_MOVE2ADD (dst_mode, reg_mode[REGNO (XEXP (src, 1))]))) { - if (reg_base_reg[REGNO (XEXP (src, 1))] < 0) + if (reg_base_reg[REGNO (XEXP (src, 1))] < 0 + && reg_symbol_ref[REGNO (XEXP (src, 1))] == NULL_RTX) offset = reg_offset[REGNO (XEXP (src, 1))]; /* Maybe the first register is known to be a constant. */ else if (reg_set_luid[REGNO (base_reg)] > move2add_last_label_luid && (MODES_OK_FOR_MOVE2ADD - (dst_mode, reg_mode[REGNO (XEXP (src, 1))])) - && reg_base_reg[REGNO (base_reg)] < 0) + (dst_mode, reg_mode[REGNO (base_reg)])) + && reg_base_reg[REGNO (base_reg)] < 0 + && reg_symbol_ref[REGNO (base_reg)] == NULL_RTX) { offset = reg_offset[REGNO (base_reg)]; base_reg = XEXP (src, 1); diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c index 04d79594b73..2a6a19846c9 100644 --- a/gcc/print-rtl.c +++ b/gcc/print-rtl.c @@ -58,6 +58,10 @@ static void print_rtx (const_rtx); the assembly output file. */ const char *print_rtx_head = ""; +#ifdef GENERATOR_FILE +/* These are defined from the .opt file when not used in generator + programs. */ + /* Nonzero means suppress output of instruction numbers in debugging dumps. This must be defined here so that programs like gencodes can be linked. */ @@ -67,6 +71,7 @@ int flag_dump_unnumbered = 0; and next insns in debugging dumps. This must be defined here so that programs like gencodes can be linked. */ int flag_dump_unnumbered_links = 0; +#endif /* Nonzero means use simplified format without flags, modes, etc. */ int flag_simple = 0; @@ -452,6 +457,9 @@ print_rtx (const_rtx in_rtx) fprintf (outfile, " %d virtual-outgoing-args", value); else if (value == VIRTUAL_CFA_REGNUM) fprintf (outfile, " %d virtual-cfa", value); + else if (value == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM) + fprintf (outfile, " %d virtual-preferred-stack-boundary", + value); else fprintf (outfile, " %d virtual-reg-%d", value, value-FIRST_VIRTUAL_REGISTER); diff --git a/gcc/print-tree.c b/gcc/print-tree.c index 5ca762eecf2..dfd358974c7 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -439,6 +439,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent) if (code == VAR_DECL && DECL_IN_TEXT_SECTION (node)) fputs (" in-text-section", file); + if (code == VAR_DECL && DECL_IN_CONSTANT_POOL (node)) + fputs (" in-constant-pool", file); if (code == VAR_DECL && DECL_COMMON (node)) fputs (" common", file); if (code == VAR_DECL && DECL_THREAD_LOCAL_P (node)) diff --git a/gcc/rtl.h b/gcc/rtl.h index f490a0c29e3..24a735ffa51 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2010,6 +2010,7 @@ enum global_rtl_index GR_VIRTUAL_STACK_DYNAMIC, GR_VIRTUAL_OUTGOING_ARGS, GR_VIRTUAL_CFA, + GR_VIRTUAL_PREFERRED_STACK_BOUNDARY, GR_MAX }; @@ -2157,7 +2158,18 @@ extern rtx gen_rtx_MEM (enum machine_mode, rtx); #define VIRTUAL_CFA_REGNUM ((FIRST_VIRTUAL_REGISTER) + 4) -#define LAST_VIRTUAL_REGISTER ((FIRST_VIRTUAL_REGISTER) + 4) +#define LAST_VIRTUAL_POINTER_REGISTER ((FIRST_VIRTUAL_REGISTER) + 4) + +/* This is replaced by crtl->preferred_stack_boundary / BITS_PER_UNIT + when finalized. */ + +#define virtual_preferred_stack_boundary_rtx \ + (global_rtl[GR_VIRTUAL_PREFERRED_STACK_BOUNDARY]) + +#define VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM \ + ((FIRST_VIRTUAL_REGISTER) + 5) + +#define LAST_VIRTUAL_REGISTER ((FIRST_VIRTUAL_REGISTER) + 5) /* Nonzero if REGNUM is a pointer into the stack frame. */ #define REGNO_PTR_FRAME_P(REGNUM) \ @@ -2166,7 +2178,7 @@ extern rtx gen_rtx_MEM (enum machine_mode, rtx); || (REGNUM) == HARD_FRAME_POINTER_REGNUM \ || (REGNUM) == ARG_POINTER_REGNUM \ || ((REGNUM) >= FIRST_VIRTUAL_REGISTER \ - && (REGNUM) <= LAST_VIRTUAL_REGISTER)) + && (REGNUM) <= LAST_VIRTUAL_POINTER_REGISTER)) /* REGNUM never really appearing in the INSN stream. */ #define INVALID_REGNUM (~(unsigned int) 0) diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 4331f416b25..d34dc806009 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -1,6 +1,6 @@ /* Analyze RTL for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -64,12 +64,6 @@ static unsigned int num_sign_bit_copies1 (const_rtx, enum machine_mode, const_rt -1 if a code has no such operand. */ static int non_rtx_starting_operands[NUM_RTX_CODE]; -/* Bit flags that specify the machine subtype we are compiling for. - Bits are tested using macros TARGET_... defined in the tm.h file - and set by `-m...' switches. Must be defined in rtlanal.c. */ - -int target_flags; - /* Truncation narrows the mode from SOURCE mode to DESTINATION mode. If TARGET_MODE_REP_EXTENDED (DESTINATION, DESTINATION_REP) is SIGN_EXTEND then while narrowing we also have to enforce the diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index fb8ba396d4f..122c45fdf64 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -2260,7 +2260,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, break; case IOR: - if (trueop1 == const0_rtx) + if (trueop1 == CONST0_RTX (mode)) return op0; if (CONST_INT_P (trueop1) && ((INTVAL (trueop1) & GET_MODE_MASK (mode)) @@ -2402,7 +2402,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, break; case XOR: - if (trueop1 == const0_rtx) + if (trueop1 == CONST0_RTX (mode)) return op0; if (CONST_INT_P (trueop1) && ((INTVAL (trueop1) & GET_MODE_MASK (mode)) diff --git a/gcc/system.h b/gcc/system.h index 8928ce6a316..178eec01b49 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -781,7 +781,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; LANG_HOOKS_MAYBE_BUILD_CLEANUP LANG_HOOKS_UPDATE_DECL_AFTER_SAVING \ LANG_HOOKS_POPLEVEL LANG_HOOKS_TRUTHVALUE_CONVERSION \ TARGET_PROMOTE_FUNCTION_ARGS TARGET_PROMOTE_FUNCTION_RETURN \ - LANG_HOOKS_MISSING_ARGUMENT + LANG_HOOKS_MISSING_ARGUMENT LANG_HOOKS_HASH_TYPES /* Miscellaneous macros that are no longer used. */ #pragma GCC poison USE_MAPPED_LOCATION diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 96955e0440c..dc21e6456d4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,434 @@ +2010-09-27 Tobias Burnus <burnus@net-b.de> + + PR fortran/40569 + PR fortran/40568 + * gfortran.dg/storage_size_2.f08: Fix test. + * gfortran.dg/c_sizeof_1.f90: Fix test. + * gfortran.dg/c_sizeof_2.f90: Update dg-error. + * gfortran.dg/c_sizeof_3.f90: New. + * gfortran.dg/c_sizeof_4.f90: New. + * gfortran.dg/iso_c_binding_compiler_1.f90: New. + * gfortran.dg/iso_c_binding_compiler_2.f90: New. + +2010-09-26 Daniel Kraft <d@domob.eu> + + PR fortran/45783 + PR fortran/45795 + * gfortran.dg/select_type_18.f03: New test. + +2010-09-25 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/return2.ad[sb]: New test. + * gnat.dg/return2_pkg.ads: New helper. + +2010-09-25 Daniel Kraft <d@domob.eu> + + PR fortran/45776 + * gfortran.dg/io_constraints_6.f03: New test. + * gfortran.dg/io_constraints_7.f03: New test. + * gfortran.dg/newunit_2.f90: New test. + +2010-09-24 Steven G. Kargl < kargl@gcc.gnu.org> + + * testsuite/gfortran.dg/operator_c1202.f90: New test. + +2010-09-24 Jan Hubicka <jh@suse.cz> + + * gcc.dg/tree-ssa/leaf.c: New testcase. + +2010-09-24 Jan Hubicka <jh@suse.cz> + + PR tree-optimization/45738 + PR tree-optimization/45741 + * gcc.c-torture/compile/pr45741.c: New. + * gfortran.fortran-torture/compile/pr45738.f90: New. + +2010-09-24 Joseph Myers <joseph@codesourcery.com> + + * gcc.dg/cpp/undef-opt-1.c: New test. + +2010-09-24 Jason Merrill <jason@redhat.com> + + * g++.dg/other/error10.C: Adjust expected output. + +2010-09-24 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/45234 + * gcc.dg/torture/stackalign/alloca-6.c: New test. + * gcc.target/i386/pr45234.c: New test. + +2010-09-24 Richard Guenther <rguenther@suse.de> + + * gcc.dg/lto/20091006-2_0.c: Prune warnings. + +2010-09-24 Marcus Shawcroft <marcus.shawcroft@arm.com> + + * g++.dg/debug/dwarf2/nested-2.C: Permit the ARM @ character + as a comment leader in regexp. + +2010-09-24 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc.dg/sync-2.m: New test. + * obj-c++.dg/sync-2.mm: New test. + +2010-09-24 Tobias Burnus <burnus@net-b.de> + + PR fortran/40571 + * gfortran.dg/iso_fortran_env_7.f90: New. + +2010-09-24 Nicola Pero <nicola.pero@meta-innovation.com> + + * obj-c++.dg/too-many-args.mm: New file. + +2010-09-24 Nicola Pero <nicola.pero@meta-innovation.com> + + Merge from 'apple/trunk' branch on FSF servers. + + 2006-03-27 Fariborz Jahanian <fjahanian@apple.com> + + Radar 4491608 + * objc.dg/too-many-args.m: New + +2010-09-23 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/45744 + * gfortran.dg/dependency_36.f90: New test. + +2010-09-23 Uros Bizjak <ubizjak@gmail.com> + + * gcc.target/i386/pad-1.c: Remove -S from dg-options. + * gcc.target/i386/pad-3.c: Ditto. + * gcc.target/i386/pad-7.c: Ditto. + * gcc.target/i386/pad-7.c: Ditto. + * gcc.target/i386/pr36502.c: Ditto. + * gcc.target/i386/zee.c: Ditto. + * gcc.target/i386/20060821-1.c: Ditto. + * gcc.target/i386/pad-2.c: Ditto. Scan for NOPs on separate lines. + * gcc.target/i386/pad-5a.c: Ditto. Do not use scan-assembler-not. + * gcc.target/i386/pad-5b.c: Ditto. + * gcc.target/i386/pad-6a.c: Ditto. + * gcc.target/i386/pad-6b.c: Ditto. + * gcc.target/i386/pad-8.c: Ditto. + * gcc.target/i386/pad-9.c: Ditto. + * gcc.target/i386/pad-10.c: Ditto. + * gcc.target/i386/pad-4.c: Ditto. Require pic effective target. + +2010-09-23 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45565 + * g++.dg/ipa/pr45565.C: New testcase. + +2010-09-23 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/45745 + PR fortran/45648 + * gfortran.dg/vector_subscript_bound_1.f90: New. + +2010-09-23 Richard Guenther <rguenther@suse.de> + + PR middle-end/45750 + * gcc.dg/pr45750.c: New testcase. + +2010-09-23 Jakub Jelinek <jakub@redhat.com> + + * gcc.dg/torture/stackalign/alloca-4.c: Remove -m32 from dg-options. + * gcc.dg/torture/stackalign/alloca-5.c: Likewise. Fix up -DDEBUG + build. + +2010-09-23 Bernd Schmidt <bernds@codesourcery.com> + + PR rtl-optimization/44374 + * gcc.target/arm/headmerge-1.c: New test. + * gcc.target/arm/headmerge-2.c: New test. + * gcc.target/i386/headmerge-1.c: New test. + * gcc.target/i386/headmerge-2.c: New test. + +2010-09-23 Daniel Kraft <d@domob.eu> + + PR fortran/38936 + PR fortran/44044 + PR fortran/45474 + * gfortran.dg/intrinsic_intent_1.f03: New test. + * gfortran.dg/select_type_17.f03: New test. + * gfortran.dg/associate_5.f03: More definability tests. + * gfortran.dg/enum_2.f90: Check definability. + * gfortran.dg/allocatable_dummy_2.f90: Change expected error message. + * gfortran.dg/allocate_alloc_opt_2.f90: Ditto. + * gfortran.dg/char_expr_2.f90: Ditto. + * gfortran.dg/deallocate_alloc_opt_2.f90: Ditto. + * gfortran.dg/enum_5.f90: Ditto. + * gfortran.dg/equiv_constraint_8.f90: Ditto. + * gfortran.dg/impure_assignment_2.f90: Ditto. + * gfortran.dg/impure_assignment_3.f90: Ditto. + * gfortran.dg/intent_out_1.f90: Ditto. + * gfortran.dg/intent_out_3.f90: Ditto. + * gfortran.dg/pointer_assign_7.f90: Ditto. + * gfortran.dg/pointer_intent_3.f90: Ditto. + * gfortran.dg/pr19936_1.f90: Ditto. + * gfortran.dg/proc_ptr_comp_3.f90: Ditto. + * gfortran.dg/simpleif_2.f90: Ditto. + * gfortran.dg/protected_5.f90: Ditto. + * gfortran.dg/protected_4.f90: Ditto and remove invalid error check. + * gfortran.dg/protected_6.f90: Ditto. + * gfortran.dg/protected_7.f90: Ditto. + +2010-09-22 Jerry DeLisle <jvdelisle@gcc.gnu.org> + + PR libfortran/45710 + * gfortran.dg/namelist_65.f90: New test. + +2010-09-22 Marcus Shawcroft <marcus.shawcroft@arm.com> + + * lib/scanasm.exp(dg-function-on-line): Permit .fnstart to appear in + the regexp pattern between the expected label and location string. + +2010-09-22 Marcus Shawcroft <marcus.shawcroft@arm.com> + + * gcc.dg/pr28706.c: Typo fix to dg-require-effective-target lto. + +2010-09-22 Marcus Shawcroft <marcus.shawcroft@arm.com> + + * gcc.dg/debug/pr41893-1.c: Typo fix to dg-require-effective-target lto. + * gcc.dg/pr27898.c: Likewise. + * gcc.dg/pr28712.c: Likewise. + * gcc.dg/pr30762-1.c: Likewise. + * gcc.dg/pr31529-1.c: Likewise. + * gcc.dg/pr34457-1.c: Likewise. + * gcc.dg/pr34668-1.c: Likewise. + * gcc.dg/pr34989-1.c: Likewise. + * gcc.dg/pr43557-1.c: Likewise. + +2010-09-22 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/45739 + * gcc.target/i386/pr45739.c: Tighten up scan-assembler-not + regexps. + +2010-09-22 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.target/sparc/mnofpu.c: New test. + +2010-09-22 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/45739 + * gcc.target/i386/pr45739.c: New test. + +2010-09-21 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/45648 + * gfortran.dg/inline_transpose_1.f90: Update temporary's locations + and counts. Add non-elemental function call check. + + PR fortran/45648 + * gfortran.dg/inline_transpose_1.f90: Add function calls with aliasing + arguments checks. Update temporary counts. + * gfortran.dg/transpose_optimization_1.f90: New. + +2010-09-21 Nicola Pero <nicola.pero@meta-innovation.com> + + PR objc/23710 + * objc.dg/invalid-method-1.m: New. + +2010-09-21 Nicola Pero <nicola.pero@meta-innovation.com> + + Merge from 'apple/trunk' branch on FSF servers. + + 2005-10-11 Fariborz Jahanian <fjahanian@apple.com> + + Radar 4291785 + * objc.dg/naming-4.m: New + * objc.dg/naming-5.m: New + * obj-c++.dg/naming-1.mm: New + * obj-c++.dg/naming-2.mm: New + +2010-09-21 Jonathan Wakely <redi@gcc.gnu.org> + Jack Howarth <howarth@bromo.med.uc.edu> + + PR c++/45645 + * g++.dg/torture/pr44972.C: Use portable assert(). + +2010-09-21 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45580 + * g++.dg/torture/pr45580.C: New testcase. + +2010-09-21 Uros Bizjak <ubizjak@gmail.com> + + * lib/gcc-dg.exp (clanup-stack-usage): Really remove .su files. + +2010-09-20 Janus Weil <janus@gcc.gnu.org> + + PR fortran/45438 + * gfortran.dg/pointer_check_7.f90: New. + +2010-09-20 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/45728 + * gcc.c-torture/compile/pr45728.c: New test. + +2010-09-20 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/45081 + * gfortran.dg/derived_array_intrinsics_1.f90 : New test. + +2010-09-20 H.J. Lu <hongjiu.lu@intel.com> + + * g++.dg/tree-ssa/pr45605.C: Add "\\". + +2010-09-20 Richard Guenther <rguenther@suse.de> + + PR middle-end/45704 + * gcc.dg/torture/pr45704.c: New testcase. + +2010-09-20 Jan Hubicka <jh@suse.cz> + + PR tree-optimize/45605 + * g++.dg/tree-ssa/pr45605.C: New testcase. + +2010-09-20 Michael Matz <matz@suse.de> + + PR testsuite/45706 + * gcc.dg/vect/pr43432.c: Don't override dg-options, defaults are + enough. + +2010-09-20 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45705 + * gcc.dg/tree-ssa/ssa-dom-dse-1.c: New testcase. + +2010-09-20 Michael Matz <matz@suse.de> + + PR testsuite/45706 + * lib/target-supports.exp (check_effective_target_vect_perm): + Add i?86-*-*. + +2010-09-20 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/45695 + * gcc.c-torture/execute/pr45695.c: New test. + +2010-09-19 Jan Hubicka <jh@suse.cz> + + PR lto/44246 + * gcc.c-torture/compile/pr44246.c:New file. + +2010-09-19 Ira Rosen <irar@il.ibm.com> + + PR tree-optimization/45714 + * gfortran.dg/vect/pr45714-a.f: New test. + * gfortran.dg/vect/pr45714-b.f: New test. + +2010-09-19 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/const1.adb: Rename into... + * gnat.dg/constant1.adb: ...this. + * gnat.dg/constant2.adb: New test. + * gnat.dg/constant2_pkg1.ads: New helper. + * gnat.dg/constant2_pkg2.ad[sb]: Likewise. + +2010-09-19 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/specs/constant1.ads: New test. + * gnat.dg/specs/constant1_pkg.ads: New helper. + +2010-09-18 Jan Hubicka <jh@suse.cz> + + PR tree-optimization/45453 + * g++.dg/tree-ssa/pr45453.C: New testcase. + +2010-09-18 Jason Merrill <jason@redhat.com> + + * g++.dg/cpp0x/initlist44.C: New. + +2010-09-18 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45709 + * g++.dg/torture/pr45709-2.C: New testcase. + +2010-09-18 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/45709 + * g++.dg/torture/pr45709.C: New testcase. + +2010-09-18 H.J. Lu <hongjiu.lu@intel.com> + + PR testsuite/45719 + * gcc.target/i386/pad-3.c: Pass -fno-pic. + +2010-09-17 H.J. Lu <hongjiu.lu@intel.com> + + * gcc.target/i386/pad-1.c: New. + * gcc.target/i386/pad-2.c: Likewise. + * gcc.target/i386/pad-3.c: Likewise. + * gcc.target/i386/pad-4.c: Likewise. + * gcc.target/i386/pad-5a.c: Likewise. + * gcc.target/i386/pad-5b.c: Likewise. + * gcc.target/i386/pad-6a.c: Likewise. + * gcc.target/i386/pad-6b.c: Likewise. + * gcc.target/i386/pad-7.c: Likewise. + * gcc.target/i386/pad-8.c: Likewise. + * gcc.target/i386/pad-9.c: Likewise. + * gcc.target/i386/pad-10.c: Likewise. + +2010-09-17 H.J. Lu <hongjiu.lu@intel.com> + + PR middle-end/45234 + * gcc.dg/torture/stackalign/alloca-5.c: New. + +2010-09-17 H.J. Lu <hongjiu.lu@intel.com> + + PR middle-end/45678 + * gcc.dg/torture/pr45678-2.c: New. + +2010-09-17 Richard Guenther <rguenther@suse.de> + + PR middle-end/45678 + * gcc.dg/torture/pr45678-1.c: New testcase. + +2010-09-17 Michael Matz <matz@suse.de> + + PR tree-optimization/43432 + * lib/target-supports.exp (check_effective_target_vect_perm_byte, + check_effective_target_vect_perm_short): New predicates. + (check_effective_target_vect_perm): Include x86_64. + * gcc.dg/vect/pr43432.c: New test. + * gcc.dg/vect/vect-114.c: Adjust. + * gcc.dg/vect/vect-15.c: Ditto. + * gcc.dg/vect/slp-perm-8.c: Use new predicate. + * gcc.dg/vect/slp-perm-9.c: Ditto. + +2010-09-17 Nicola Pero <nicola.pero@meta-innovation.com> + + PR testsuite/45692 + * objc/execute/exceptions/throw-nil.m: Run the test only with the + GNU runtime. + +2010-09-17 Richard Guenther <rguenther@suse.de> + + * gcc.dg/pr27898.c: Use -flto instead of -combine. + * gcc.dg/pr28706.c: Likewise. + * gcc.dg/pr28712.c: Likewise. + * gcc.dg/pr30762-1.c: Likewise. + * gcc.dg/pr30762-2.c: Likewise. + * gcc.dg/pr31529-1.c: Likewise. + * gcc.dg/pr31529-2.c: Likewise. + * gcc.dg/pr34457-1.c: Likewise. + * gcc.dg/pr34457-2.c: Likewise. + * gcc.dg/pr34668-1.c: Likewise. + * gcc.dg/pr34668-2.c: Likewise. + * gcc.dg/pr34989-1.c: Likewise. + * gcc.dg/pr34989-2.c: Likewise. + * gcc.dg/pr43557-1.c: Likewise. + * gcc.dg/pr43557-2.c: Likewise. + * gcc.dg/debug/pr41893-1.c: Likewise. + * gcc.dg/matrix/matrix.exp: Do not use -combine. + * gcc.dg/matrix/matrix-3.c: Drop dg-options. + * gcc.dg/matrix/matrix-4.c: Likewise. + * gcc.dg/struct/struct-reorg.exp: Do not use -combine. + * gcc.dg/struct/wo_prof_empty_str.c: Drop dg-options. + * gcc.dg/struct/wo_prof_escape_arg_to_local.c: Likewise. + * gcc.dg/struct/wo_prof_escape_return.c: Likewise. + 2010-09-16 Tobias Burnus <burnus@net-b.de> PR fortran/43665 @@ -8108,7 +8539,7 @@ * gfortran.dg/read_x_eof.f90: New test. * gfortran.dg/read_x_past.f: Update test. -2010-03-10 Jan Hubicka <jh@suse.cz> +2010-03-10 Jan Hubicka <jh@suse.cz> * gcc.c-torture/compile/pr43288.c: New test. diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist44.C b/gcc/testsuite/g++.dg/cpp0x/initlist44.C new file mode 100644 index 00000000000..fbe0ea3fefe --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist44.C @@ -0,0 +1,5 @@ +// { dg-options -std=c++0x } + +#include <initializer_list> + +auto value = std::initializer_list<int>{ 1, 2, 3 }; diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/nested-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/nested-2.C index 2ab0c375cc0..65d382be4f9 100644 --- a/gcc/testsuite/g++.dg/debug/dwarf2/nested-2.C +++ b/gcc/testsuite/g++.dg/debug/dwarf2/nested-2.C @@ -32,6 +32,6 @@ We want to express that the DIE of S::T<int> must be a child of the DIE of S, li Hence the slightly odd regexp: - { dg-final { scan-assembler "\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_structure_type\\)\[\n\r\]+\[^\n\r\]*\"S\\\\0\"\[ \t\]+\(#|!|//?\)\[ \t\]+DW_AT_name\[\n\r\]+\(.*\)?\\(DIE\[^\n\r\]*DW_TAG_structure_type\\)\[\n\r\]+\[^\n\r\]*\"T<int>\\\\0\"\[ \t\]+\(.*\)?\\(DIE\[^\n\r\]*DW_TAG_template_type_param\\)\[\n\r\]+\[^\n\r\]*\[\n\r\]+\[^\n\r\]*\[\n\r\]+\[^\n\r\]*\(#|!|//?\)\[ \t\]+end of children of DIE\[^\n\r\]*\[\n\r\]+\[^\n\r\]*end of children of DIE\[^\n\r\]*" } } + { dg-final { scan-assembler "\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_structure_type\\)\[\n\r\]+\[^\n\r\]*\"S\\\\0\"\[ \t\]+\(@|#|!|//?\)\[ \t\]+DW_AT_name\[\n\r\]+\(.*\)?\\(DIE\[^\n\r\]*DW_TAG_structure_type\\)\[\n\r\]+\[^\n\r\]*\"T<int>\\\\0\"\[ \t\]+\(.*\)?\\(DIE\[^\n\r\]*DW_TAG_template_type_param\\)\[\n\r\]+\[^\n\r\]*\[\n\r\]+\[^\n\r\]*\[\n\r\]+\[^\n\r\]*\(@|#|!|//?\)\[ \t\]+end of children of DIE\[^\n\r\]*\[\n\r\]+\[^\n\r\]*end of children of DIE\[^\n\r\]*" } } */ diff --git a/gcc/testsuite/g++.dg/ipa/pr45565.C b/gcc/testsuite/g++.dg/ipa/pr45565.C new file mode 100644 index 00000000000..c04de12e271 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr45565.C @@ -0,0 +1,29 @@ +// { dg-do compile } +// { dg-options "-O -fno-toplevel-reorder -fno-inline -fipa-cp -fipa-cp-clone -fkeep-inline-functions" } + +template < typename Derived > struct AnyMatrixBase +{ +}; + +struct Matrix Random (); + +struct Matrix:AnyMatrixBase < Matrix > +{ + void bar () + { + throw; + } + void foo (Matrix other) + { + bar (); + Matrix (AnyMatrixBase < Matrix > (Random ())); + } + template + < typename OtherDerived > Matrix (AnyMatrixBase < OtherDerived > other) + { + foo (other); + } +}; + +Matrix x (Random ()); + diff --git a/gcc/testsuite/g++.dg/other/error10.C b/gcc/testsuite/g++.dg/other/error10.C index 9e6da6529aa..26f7ca53f29 100644 --- a/gcc/testsuite/g++.dg/other/error10.C +++ b/gcc/testsuite/g++.dg/other/error10.C @@ -6,7 +6,7 @@ template<int> struct A {}; template<int N> void foo(const A<N> &a) -{ -A<N>(a); } // { dg-error "\\(\\(const A<0>\\*\\)a\\)" "" } +{ -A<N>(a); } // { dg-error "\\(\\* & a\\)" "" } void bar() { diff --git a/gcc/testsuite/g++.dg/torture/pr44972.C b/gcc/testsuite/g++.dg/torture/pr44972.C index 81806076c58..e409148da1c 100644 --- a/gcc/testsuite/g++.dg/torture/pr44972.C +++ b/gcc/testsuite/g++.dg/torture/pr44972.C @@ -74,7 +74,7 @@ class optional : public optional_base<T> T const& get() const ; - T const* operator->() const { ((this->is_initialized()) ? static_cast<void> (0) : __assert_fail ("this->is_initialized()", "pr44972.C", 78, __PRETTY_FUNCTION__)) ; return this->get_ptr_impl() ; } + T const* operator->() const { assert(this->is_initialized()) ; return this->get_ptr_impl() ; } } ; diff --git a/gcc/testsuite/g++.dg/torture/pr45580.C b/gcc/testsuite/g++.dg/torture/pr45580.C new file mode 100644 index 00000000000..c3af4910aeb --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr45580.C @@ -0,0 +1,50 @@ +// { dg-do compile } + +namespace std { + typedef __SIZE_TYPE__ size_t; +} +inline void* operator new(std::size_t, void* __p) throw() { + return __p; +} +class Noncopyable { }; +struct CollectorCell { }; +template<typename T> class PassRefPtr { +public: + T* releaseRef() const { } +}; +template <typename T> class NonNullPassRefPtr { +public: + template <class U> NonNullPassRefPtr(const PassRefPtr<U>& o) + : m_ptr(o.releaseRef()) { } + mutable T* m_ptr; +}; +struct ClassInfo; +class JSValue { }; +JSValue jsNull(); +class Structure; +class JSGlobalData { + static void storeVPtrs(); +}; +class JSCell : public Noncopyable { + friend class JSObject; + friend class JSGlobalData; + virtual ~JSCell(); +}; +class JSObject : public JSCell { +public: + explicit JSObject(NonNullPassRefPtr<Structure>); + static PassRefPtr<Structure> createStructure(JSValue prototype) { } +}; +class JSByteArray : public JSObject { + friend class JSGlobalData; + enum VPtrStealingHackType { VPtrStealingHack }; + JSByteArray(VPtrStealingHackType) + : JSObject(createStructure(jsNull())), m_classInfo(0) { } + const ClassInfo* m_classInfo; +}; +void JSGlobalData::storeVPtrs() { + CollectorCell cell; + void* storage = &cell; + JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack); + jsByteArray->~JSCell(); +} diff --git a/gcc/testsuite/g++.dg/torture/pr45709-2.C b/gcc/testsuite/g++.dg/torture/pr45709-2.C new file mode 100644 index 00000000000..1f6a2344f04 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr45709-2.C @@ -0,0 +1,20 @@ +// { dg-do compile } + +struct Region { + int storage[4]; + int count; +}; +static inline Region subtract(int lhs) +{ + Region reg; + int* storage = reg.storage; + int* storage2 = reg.storage; + if (lhs > 0) + storage++, storage2--; + reg.count = storage - reg.storage + storage2 - reg.storage; + return reg; +} +void bar(int a) +{ + const Region copyBack(subtract(a)); +} diff --git a/gcc/testsuite/g++.dg/torture/pr45709.C b/gcc/testsuite/g++.dg/torture/pr45709.C new file mode 100644 index 00000000000..1584ec76a99 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr45709.C @@ -0,0 +1,19 @@ +// { dg-do compile } + +struct Region { + int storage[4]; + int count; +}; +static inline Region subtract(int lhs) +{ + Region reg; + int* storage = reg.storage; + if (lhs > 0) + storage++; + reg.count = storage - reg.storage; + return reg; +} +void bar(int a) +{ + const Region copyBack(subtract(a)); +} diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr45453.C b/gcc/testsuite/g++.dg/tree-ssa/pr45453.C new file mode 100644 index 00000000000..78c6460f727 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr45453.C @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +struct S +{ + S(); + virtual inline void foo () + { + foo(); + } +}; + +void +B () +{ + S().foo (); +} +/* We should inline foo and devirtualize call to foo in the inlined version. */ +// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 1 "optimized" } } +// { dg-final { cleanup-tree-dump "optimized" } } diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr45605.C b/gcc/testsuite/g++.dg/tree-ssa/pr45605.C new file mode 100644 index 00000000000..20c4ba88045 --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr45605.C @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-ssa" } */ +extern "C" void abort(); +bool destructor_called = false; + +struct B { + virtual void Run(){}; +}; + +struct D : public B { + virtual void Run() + { + struct O { + ~O() { destructor_called = true; }; + } o; + + struct Raiser { + Raiser() throw( int ) {throw 1;}; + } raiser; + }; +}; + +int main() { + try { + D d; + static_cast<B&>(d).Run(); + } catch (...) {} + + if (!destructor_called) + abort (); +} + + + +/* We should devirtualize call to D::Run */ +/* { dg-final { scan-tree-dump-times "D::Run \\(" 1 "ssa"} } */ +/* { dg-final { cleanup-tree-dump "ssa" } } */ diff --git a/gcc/testsuite/gcc.c-torture/compile/pr44246.c b/gcc/testsuite/gcc.c-torture/compile/pr44246.c new file mode 100644 index 00000000000..6e478690351 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr44246.c @@ -0,0 +1,5 @@ +int main(int argc, char *argv[]) +{ + strcat(argv[0], "X"); + return strlen(argv[0]); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr45728.c b/gcc/testsuite/gcc.c-torture/compile/pr45728.c new file mode 100644 index 00000000000..a6ee10b8cd1 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr45728.c @@ -0,0 +1,17 @@ +/* PR rtl-optimization/45728 */ + +union U +{ + int *m; + double d; +}; + +int i; +union U u; + +int +foo (void) +{ + union U v = { &i }; + return u.d == v.d; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr45771.c b/gcc/testsuite/gcc.c-torture/compile/pr45771.c new file mode 100644 index 00000000000..2bd96eccc5a --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr45771.c @@ -0,0 +1,7 @@ +static const int data[2048]; + +void foo (void *ptr) +{ + __builtin_memcmp (data, ptr, 1); +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/pr45695.c b/gcc/testsuite/gcc.c-torture/execute/pr45695.c new file mode 100644 index 00000000000..eb1e4c788ab --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr45695.c @@ -0,0 +1,32 @@ +/* PR rtl-optimization/45695 */ + +extern void abort (void); + +__attribute__((noinline)) void +g (int x) +{ + asm volatile ("" : "+r" (x)); +} + +__attribute__((noinline)) int +f (int a, int b, int d) +{ + int r = -1; + b += d; + if (d == a) + r = b - d; + g (b); + return r; +} + +int +main (void) +{ + int l; + asm ("" : "=r" (l) : "0" (0)); + if (f (l + 0, l + 1, l + 4) != -1) + abort (); + if (f (l + 4, l + 1, l + 4) != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/cpp/undef-opt-1.c b/gcc/testsuite/gcc.dg/cpp/undef-opt-1.c new file mode 100644 index 00000000000..99c524662c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/undef-opt-1.c @@ -0,0 +1,8 @@ +/* Test -undef. A bug in its handling broke glibc builds because + "linux" was wrongly defined. */ +/* { dg-do preprocess } */ +/* { dg-options "-undef" } */ + +#ifdef linux +#error -undef broken +#endif diff --git a/gcc/testsuite/gcc.dg/debug/pr41893-1.c b/gcc/testsuite/gcc.dg/debug/pr41893-1.c index 54a31fb6f2f..150fdefc913 100644 --- a/gcc/testsuite/gcc.dg/debug/pr41893-1.c +++ b/gcc/testsuite/gcc.dg/debug/pr41893-1.c @@ -1,6 +1,7 @@ /* PR debug/41893 */ -/* { dg-do compile } */ -/* { dg-options "-combine -fwhole-program -O" } */ +/* { dg-do link } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -fwhole-program -O -r -nostdlib" } */ /* { dg-additional-sources "pr41893-2.c" } */ struct S { int v; }; diff --git a/gcc/testsuite/gcc.dg/lto/20091006-2_0.c b/gcc/testsuite/gcc.dg/lto/20091006-2_0.c index f8189920cfd..abe12c40c68 100644 --- a/gcc/testsuite/gcc.dg/lto/20091006-2_0.c +++ b/gcc/testsuite/gcc.dg/lto/20091006-2_0.c @@ -1,4 +1,5 @@ /* { dg-lto-do link } */ +/* { dg-extra-ld-options "-w" } */ extern int a[10]; int main() { return 0; } diff --git a/gcc/testsuite/gcc.dg/matrix/matrix-3.c b/gcc/testsuite/gcc.dg/matrix/matrix-3.c index 5990abf48a6..28a5a16b7e0 100644 --- a/gcc/testsuite/gcc.dg/matrix/matrix-3.c +++ b/gcc/testsuite/gcc.dg/matrix/matrix-3.c @@ -1,6 +1,4 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -fipa-matrix-reorg -fdump-ipa-matrix-reorg -c -fwhole-program -combine" } */ - #include <stdio.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/matrix/matrix-4.c b/gcc/testsuite/gcc.dg/matrix/matrix-4.c index 7ca79ec4b5a..d741b46e416 100644 --- a/gcc/testsuite/gcc.dg/matrix/matrix-4.c +++ b/gcc/testsuite/gcc.dg/matrix/matrix-4.c @@ -1,6 +1,4 @@ /* { dg-do compile } */ -/* { dg-options "-O3 -fipa-matrix-reorg -fdump-ipa-matrix-reorg -c -fwhole-program -combine" } */ - #include <stdio.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/matrix/matrix.exp b/gcc/testsuite/gcc.dg/matrix/matrix.exp index b2f4ede9448..fc1eb4138bf 100644 --- a/gcc/testsuite/gcc.dg/matrix/matrix.exp +++ b/gcc/testsuite/gcc.dg/matrix/matrix.exp @@ -19,7 +19,7 @@ load_lib gcc-dg.exp load_lib target-supports.exp -set DEFAULT_MATCFLAGS "-O3 -fipa-matrix-reorg -fdump-ipa-matrix-reorg -fwhole-program -combine" +set DEFAULT_MATCFLAGS "-O3 -fipa-matrix-reorg -fdump-ipa-matrix-reorg -fwhole-program" # Initialize `dg'. dg-init @@ -52,7 +52,7 @@ load_lib profopt.exp # needed to generate profile data, the second is options to use the # profile data. set profile_option "-fprofile-generate -O3" -set feedback_option "-fprofile-use -fipa-matrix-reorg -fdump-ipa-matrix-reorg -O3 -fwhole-program -combine" +set feedback_option "-fprofile-use -fipa-matrix-reorg -fdump-ipa-matrix-reorg -O3 -fwhole-program" foreach src [lsort [glob -nocomplain $srcdir/$subdir/transpose-*.c]] { # If we're only testing specific files and this isn't one of them, skip it. diff --git a/gcc/testsuite/gcc.dg/pr27898.c b/gcc/testsuite/gcc.dg/pr27898.c index bb7cce17550..2763a498a1e 100644 --- a/gcc/testsuite/gcc.dg/pr27898.c +++ b/gcc/testsuite/gcc.dg/pr27898.c @@ -1,6 +1,7 @@ /* PR c/27898 */ -/* { dg-do compile } */ -/* { dg-options "--combine" } */ +/* { dg-do link } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -r -nostdlib" } */ /* { dg-additional-sources "pr27898.c" } */ union u { struct { int i; }; }; diff --git a/gcc/testsuite/gcc.dg/pr28706.c b/gcc/testsuite/gcc.dg/pr28706.c index 4c185af4123..1ecb8b22929 100644 --- a/gcc/testsuite/gcc.dg/pr28706.c +++ b/gcc/testsuite/gcc.dg/pr28706.c @@ -1,6 +1,7 @@ /* PR c/28706 */ -/* { dg-do compile } */ -/* { dg-options "--combine" } */ +/* { dg-do link } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -r -nostdlib" } */ /* { dg-additional-sources "pr28706.c" } */ struct A diff --git a/gcc/testsuite/gcc.dg/pr28712.c b/gcc/testsuite/gcc.dg/pr28712.c index 0bbb45314cf..f398321d8af 100644 --- a/gcc/testsuite/gcc.dg/pr28712.c +++ b/gcc/testsuite/gcc.dg/pr28712.c @@ -1,6 +1,7 @@ /* PR c/28712 */ -/* { dg-do compile } */ -/* { dg-options "--combine" } */ +/* { dg-do link } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -r -nostdlib" } */ /* { dg-additional-sources "pr28712.c pr28712.c" } */ struct A; diff --git a/gcc/testsuite/gcc.dg/pr30762-1.c b/gcc/testsuite/gcc.dg/pr30762-1.c index 97dca8c020e..74a566aa55c 100644 --- a/gcc/testsuite/gcc.dg/pr30762-1.c +++ b/gcc/testsuite/gcc.dg/pr30762-1.c @@ -1,6 +1,7 @@ /* PR c/30762 */ -/* { dg-do compile } */ -/* { dg-options "--combine -O3" } */ +/* { dg-do link } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -r -nostdlib -O3" } */ /* { dg-additional-sources pr30762-2.c } */ typedef struct { int i; } D; diff --git a/gcc/testsuite/gcc.dg/pr31529-1.c b/gcc/testsuite/gcc.dg/pr31529-1.c index 20703ed2538..31339e1ef83 100644 --- a/gcc/testsuite/gcc.dg/pr31529-1.c +++ b/gcc/testsuite/gcc.dg/pr31529-1.c @@ -1,5 +1,6 @@ -/* { dg-do compile } */ -/* { dg-options "-combine" } */ +/* { dg-do link } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -r -nostdlib" } */ /* { dg-additional-sources "pr31529-2.c" } */ getline () diff --git a/gcc/testsuite/gcc.dg/pr34457-1.c b/gcc/testsuite/gcc.dg/pr34457-1.c index ccd937c6b52..3ccee11d1b3 100644 --- a/gcc/testsuite/gcc.dg/pr34457-1.c +++ b/gcc/testsuite/gcc.dg/pr34457-1.c @@ -1,7 +1,8 @@ /* PR c/34457 */ -/* { dg-do compile } */ +/* { dg-do link } */ /* { dg-require-effective-target trampolines } */ -/* { dg-options "--combine -O2" } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -r -nostdlib -O2" } */ /* { dg-additional-sources "pr34457-2.c" } */ diff --git a/gcc/testsuite/gcc.dg/pr34668-1.c b/gcc/testsuite/gcc.dg/pr34668-1.c index 5763bb61027..59495667cb4 100644 --- a/gcc/testsuite/gcc.dg/pr34668-1.c +++ b/gcc/testsuite/gcc.dg/pr34668-1.c @@ -1,6 +1,7 @@ /* PR c/34668 */ -/* { dg-do compile } */ -/* { dg-options "--combine -O2" } */ +/* { dg-do link } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -r -nostdlib -O2" } */ /* { dg-additional-sources "pr34668-2.c" } */ struct optab { unsigned code; }; diff --git a/gcc/testsuite/gcc.dg/pr34989-1.c b/gcc/testsuite/gcc.dg/pr34989-1.c index 88e8d64c64e..47d83639e7f 100644 --- a/gcc/testsuite/gcc.dg/pr34989-1.c +++ b/gcc/testsuite/gcc.dg/pr34989-1.c @@ -1,5 +1,6 @@ -/* { dg-do compile } */ -/* { dg-options "--combine -O2" } */ +/* { dg-do link } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -r -nostdlib -O2" } */ /* { dg-additional-sources "pr34989-2.c" } */ extern struct globals *const ptr_to_globals; diff --git a/gcc/testsuite/gcc.dg/pr43557-1.c b/gcc/testsuite/gcc.dg/pr43557-1.c index 8c7d0b4176e..dd6667c771e 100644 --- a/gcc/testsuite/gcc.dg/pr43557-1.c +++ b/gcc/testsuite/gcc.dg/pr43557-1.c @@ -1,6 +1,7 @@ /* PR debug/43557 */ -/* { dg-do compile } */ -/* { dg-options "--combine -g -O2" } */ +/* { dg-do link } */ +/* { dg-require-effective-target lto } */ +/* { dg-options "-flto -r -nostdlib -g -O2" } */ /* { dg-additional-sources "pr43557-2.c" } */ struct S diff --git a/gcc/testsuite/gcc.dg/pr45750.c b/gcc/testsuite/gcc.dg/pr45750.c new file mode 100644 index 00000000000..22c471b7070 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr45750.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +struct S +{ + int i; +}; + +int invalid[] = 0; /* { dg-error "invalid initializer" } */ + +void foo (void) +{ + if (((struct S *)undeclared)->i); /* { dg-error "undeclared" } */ +} + +/* { dg-message "reported only once" "" { target *-*-* } 13 } */ diff --git a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp index c96501c2980..34ec94ee29b 100644 --- a/gcc/testsuite/gcc.dg/struct/struct-reorg.exp +++ b/gcc/testsuite/gcc.dg/struct/struct-reorg.exp @@ -20,7 +20,7 @@ load_lib gcc-dg.exp load_lib target-supports.exp -set STRUCT_REORG_CFLAGS "-O3 -fipa-struct-reorg -fdump-ipa-all -fwhole-program -combine" +set STRUCT_REORG_CFLAGS "-O3 -fipa-struct-reorg -fdump-ipa-all -fwhole-program" # Initialize `dg'. dg-init @@ -51,7 +51,7 @@ load_lib profopt.exp # These are globals used by profopt-execute. The first is options # needed to generate profile data, the second is options to use the # profile data. -set common "-O3 -fwhole-program -combine" +set common "-O3 -fwhole-program" set profile_option [concat $common " -fprofile-generate"] set feedback_option [concat $common " -fprofile-use -fipa-struct-reorg -fdump-ipa-all"] diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_empty_str.c b/gcc/testsuite/gcc.dg/struct/wo_prof_empty_str.c index 58411202767..09668face34 100644 --- a/gcc/testsuite/gcc.dg/struct/wo_prof_empty_str.c +++ b/gcc/testsuite/gcc.dg/struct/wo_prof_empty_str.c @@ -1,5 +1,3 @@ -/* { dg-options "-O3 -fno-inline -fdump-ipa-all -fipa-struct-reorg -fwhole-program -combine" } */ -/* { dg-do compile } */ /* { dg-do run } */ #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_arg_to_local.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_arg_to_local.c index 781a847f9f7..0116d819800 100644 --- a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_arg_to_local.c +++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_arg_to_local.c @@ -1,5 +1,3 @@ -/* { dg-options "-O3 -fno-inline -fno-ipa-sra -fdump-ipa-all -fipa-struct-reorg -fwhole-program -combine" } */ -/* { dg-do compile } */ /* { dg-do run } */ #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_return.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_return.c index 8892fa99098..21a6a7f3a2e 100644 --- a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_return.c +++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_return.c @@ -1,5 +1,3 @@ -/* { dg-options "-O3 -fno-inline -fdump-ipa-all -fipa-struct-reorg -fwhole-program -combine" } */ -/* { dg-do compile } */ /* { dg-do run } */ #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/torture/pr45678-1.c b/gcc/testsuite/gcc.dg/torture/pr45678-1.c new file mode 100644 index 00000000000..58e6156e9f4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr45678-1.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ + +typedef float V __attribute__ ((vector_size (16))); +V g; +float d[4] = { 4, 3, 2, 1 }; + +int +main () +{ + V e; + __builtin_memcpy (&e, &d, sizeof (d)); + V f = { 5, 15, 25, 35 }; + e = e * f; + g = e; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr45678-2.c b/gcc/testsuite/gcc.dg/torture/pr45678-2.c new file mode 100644 index 00000000000..449404cda1a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr45678-2.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ + +typedef float V __attribute__ ((vector_size (16))); +V g; + +int +main () +{ + float d[4] = { 4, 3, 2, 1 }; + V e; + __builtin_memcpy (&e, &d, sizeof (d)); + V f = { 5, 15, 25, 35 }; + e = e * f; + g = e; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr45704.c b/gcc/testsuite/gcc.dg/torture/pr45704.c new file mode 100644 index 00000000000..487b30a96c0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr45704.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-optimized" } */ + +struct st { + int ptr; +}; + +int foo(struct st *st) +{ + int v = *(volatile int *)&st->ptr; + return v & 0xff; +} + +/* { dg-final { scan-tree-dump-times "={v}" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/stackalign/alloca-4.c b/gcc/testsuite/gcc.dg/torture/stackalign/alloca-4.c new file mode 100644 index 00000000000..c3e554acf02 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/stackalign/alloca-4.c @@ -0,0 +1,41 @@ +/* PR middle-end/37009 */ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ +/* { dg-options "-mincoming-stack-boundary=2 -mpreferred-stack-boundary=2" } */ + +#include "check.h" + +void +bar (char *p, int size) +{ + __builtin_strncpy (p, "good", size); +} + +void +__attribute__ ((noinline)) +foo (double x, double y ,double z ,double a, int size) +{ + char *p = __builtin_alloca (size + 1); + double i; + + bar (p, size); + if (__builtin_strncmp (p, "good", size) != 0) + { +#ifdef DEBUG + p[size] = '\0'; + printf ("Failed: %s != good\n", p); +#endif + abort (); + } + + check (&i, __alignof__(i)); +} + +int +main (void) +{ + double x = 1.0 ; + + foo (x, x, x, x, 5); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/stackalign/alloca-5.c b/gcc/testsuite/gcc.dg/torture/stackalign/alloca-5.c new file mode 100644 index 00000000000..2ef4443f283 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/stackalign/alloca-5.c @@ -0,0 +1,32 @@ +/* PR middle-end/45234 */ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ +/* { dg-options "-mincoming-stack-boundary=2 -mpreferred-stack-boundary=2" } */ + +#include "check.h" + +void +__attribute__ ((noinline)) +bar (__float128 f) +{ + check (&f, __alignof__(f)); +} + +int +main (void) +{ + char *p = __builtin_alloca (6); + + bar (0); + + __builtin_strncpy (p, "good", 5); + if (__builtin_strncmp (p, "good", 5) != 0) + { +#ifdef DEBUG + p[5] = '\0'; + printf ("Failed: %s != good\n", p); +#endif + abort (); + } + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/stackalign/alloca-6.c b/gcc/testsuite/gcc.dg/torture/stackalign/alloca-6.c new file mode 100644 index 00000000000..f0e4513de0e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/stackalign/alloca-6.c @@ -0,0 +1,34 @@ +/* PR middle-end/45234 */ +/* { dg-do run { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ +/* { dg-options "-mincoming-stack-boundary=2 -mpreferred-stack-boundary=2" } */ + +#include "check.h" + +void +__attribute__ ((noinline)) +bar (__float128 f) +{ + check (&f, __alignof__(f)); +} + +volatile int z = 6; + +int +main (void) +{ + char *p = __builtin_alloca (z); + + bar (0); + + __builtin_strncpy (p, "good", 5); + if (__builtin_strncmp (p, "good", 5) != 0) + { +#ifdef DEBUG + p[z - 1] = '\0'; + printf ("Failed: %s != good\n", p); +#endif + abort (); + } + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/leaf.c b/gcc/testsuite/gcc.dg/tree-ssa/leaf.c new file mode 100644 index 00000000000..936523a930d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/leaf.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +static int local_static; +void __attribute__ ((leaf)) leaf_call (void); + +int +clobber_it (void) +{ + return local_static++; +} +int +test (void) +{ + local_static = 9; + leaf_call (); + return local_static; +} +/* { dg-final { scan-tree-dump-times "return 9" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-dse-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-dse-1.c new file mode 100644 index 00000000000..504e4bc038d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-dse-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int x; +void +foo (void) +{ + if (x == 0) + x = 0; +} +void +bar (int i) +{ + if (x == i) + x = i; +} + +/* { dg-final { scan-tree-dump-not "x =" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr43432.c b/gcc/testsuite/gcc.dg/vect/pr43432.c new file mode 100644 index 00000000000..18c0dba56f6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr43432.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float } */ + + +void vector_fmul_reverse_c(float *dst, const float *src0, const float *src1, +int len){ + int i; + src1 += len-1; + for(i=0; i<len; i++) + dst[i] = src0[i] * src1[-i]; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_perm } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-8.c b/gcc/testsuite/gcc.dg/vect/slp-perm-8.c index 28c3529c514..deec308449b 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-8.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-8.c @@ -53,7 +53,7 @@ int main (int argc, const char* argv[]) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target vect_perm } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_perm } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target vect_perm_byte } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_perm_byte } } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-perm-9.c b/gcc/testsuite/gcc.dg/vect/slp-perm-9.c index 5c5176e716b..f4387299622 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-perm-9.c +++ b/gcc/testsuite/gcc.dg/vect/slp-perm-9.c @@ -54,7 +54,7 @@ int main (int argc, const char* argv[]) } /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ -/* { dg-final { scan-tree-dump-times "permutation requires at least three vectors" 1 "vect" { target vect_perm } } } */ +/* { dg-final { scan-tree-dump-times "permutation requires at least three vectors" 1 "vect" { target vect_perm_short } } } */ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-114.c b/gcc/testsuite/gcc.dg/vect/vect-114.c index 035c9a89c2a..f9132acd06d 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-114.c +++ b/gcc/testsuite/gcc.dg/vect/vect-114.c @@ -34,6 +34,7 @@ int main (void) return main1 (); } -/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! vect_perm } } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-15.c b/gcc/testsuite/gcc.dg/vect/vect-15.c index b2ae9c8471d..87853c1248e 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-15.c +++ b/gcc/testsuite/gcc.dg/vect/vect-15.c @@ -35,5 +35,5 @@ int main (void) return main1 (); } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.target/arm/headmerge-1.c b/gcc/testsuite/gcc.target/arm/headmerge-1.c new file mode 100644 index 00000000000..218c6a21ebd --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/headmerge-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-times "#120" 1 } } */ + +extern void foo1 (int); +extern void foo2 (int); + +void t (int x, int y) +{ + if (y < 5) + foo1 (120); + else + foo2 (120); +} diff --git a/gcc/testsuite/gcc.target/arm/headmerge-2.c b/gcc/testsuite/gcc.target/arm/headmerge-2.c new file mode 100644 index 00000000000..36637a64eb3 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/headmerge-2.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-times "120" 1 } } */ + +extern void foo1 (int); +extern void foo2 (int); +extern void foo3 (int); +extern void foo4 (int); +extern void foo5 (int); +extern void foo6 (int); + +void t (int x, int y) +{ + switch (y) + { + case 1: + foo1 (120); + break; + case 5: + foo2 (120); + break; + case 7: + foo3 (120); + break; + case 10: + foo4 (120); + break; + case 13: + foo5 (120); + break; + default: + foo6 (120); + break; + } +} diff --git a/gcc/testsuite/gcc.target/i386/20060821-1.c b/gcc/testsuite/gcc.target/i386/20060821-1.c index 56e980fddfb..29a9afe876c 100644 --- a/gcc/testsuite/gcc.target/i386/20060821-1.c +++ b/gcc/testsuite/gcc.target/i386/20060821-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -msse3 -S" } */ +/* { dg-options "-O2 -msse3" } */ /* { dg-final { scan-assembler-not "%mm" } } */ /* PR 28825 */ #include <pmmintrin.h> diff --git a/gcc/testsuite/gcc.target/i386/headmerge-1.c b/gcc/testsuite/gcc.target/i386/headmerge-1.c new file mode 100644 index 00000000000..941028c31db --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/headmerge-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-times "120" 1 } } */ + +extern void foo1 (int); +extern void foo2 (int); + +void t (int x, int y) +{ + if (y < 5) + foo1 (120); + else + foo2 (120); +} diff --git a/gcc/testsuite/gcc.target/i386/headmerge-2.c b/gcc/testsuite/gcc.target/i386/headmerge-2.c new file mode 100644 index 00000000000..36637a64eb3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/headmerge-2.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-times "120" 1 } } */ + +extern void foo1 (int); +extern void foo2 (int); +extern void foo3 (int); +extern void foo4 (int); +extern void foo5 (int); +extern void foo6 (int); + +void t (int x, int y) +{ + switch (y) + { + case 1: + foo1 (120); + break; + case 5: + foo2 (120); + break; + case 7: + foo3 (120); + break; + case 10: + foo4 (120); + break; + case 13: + foo5 (120); + break; + default: + foo6 (120); + break; + } +} diff --git a/gcc/testsuite/gcc.target/i386/pad-1.c b/gcc/testsuite/gcc.target/i386/pad-1.c new file mode 100644 index 00000000000..770c44d8900 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fomit-frame-pointer -mtune=generic" } */ +/* { dg-final { scan-assembler "rep" } } */ +/* { dg-final { scan-assembler-not "nop" } } */ + +void +foo () +{ +} diff --git a/gcc/testsuite/gcc.target/i386/pad-10.c b/gcc/testsuite/gcc.target/i386/pad-10.c new file mode 100644 index 00000000000..e10d24c7da6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-10.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom" } */ +/* { dg-final { scan-assembler-not "nop" } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +extern void bar (); + +int +foo2 (int z, int x) +{ + if (x == 1) + { + bar (); + return z; + } + else + return x + z; +} diff --git a/gcc/testsuite/gcc.target/i386/pad-2.c b/gcc/testsuite/gcc.target/i386/pad-2.c new file mode 100644 index 00000000000..37743c483a8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-2.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom" } */ +/* { dg-final { scan-assembler-times "nop" 8 } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +void +foo () +{ +} diff --git a/gcc/testsuite/gcc.target/i386/pad-3.c b/gcc/testsuite/gcc.target/i386/pad-3.c new file mode 100644 index 00000000000..b9a547d07d8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-3.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom -fno-pic" } */ +/* { dg-final { scan-assembler-not "nop" } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +int s[8] = {1, 2, 3, 4, 5, 6, 7, 8}; +int d[8] = {11, 22, 33, 44, 55, 66, 77, 88}; + +void +foo () +{ + int i; + for (i = 0; i < 8; i++) + d[i] = s[i] + 0x1000; +} diff --git a/gcc/testsuite/gcc.target/i386/pad-4.c b/gcc/testsuite/gcc.target/i386/pad-4.c new file mode 100644 index 00000000000..ad6b029e2cb --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-4.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom -fPIC" } */ +/* { dg-final { scan-assembler-times "nop" 8 } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +extern int bar; + +int +foo () +{ + asm volatile (""); + return bar; +} diff --git a/gcc/testsuite/gcc.target/i386/pad-5a.c b/gcc/testsuite/gcc.target/i386/pad-5a.c new file mode 100644 index 00000000000..d29e62816f0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-5a.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom" } */ +/* { dg-final { scan-assembler-times "nop" 2 } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +int +foo (int x, int y, int z) +{ + return x + y + z; +} diff --git a/gcc/testsuite/gcc.target/i386/pad-5b.c b/gcc/testsuite/gcc.target/i386/pad-5b.c new file mode 100644 index 00000000000..1d95bf32d2f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-5b.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom" } */ +/* { dg-final { scan-assembler-times "nop" 4 } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +int +foo (int x, int y, int z) +{ + return x + y + z; +} diff --git a/gcc/testsuite/gcc.target/i386/pad-6a.c b/gcc/testsuite/gcc.target/i386/pad-6a.c new file mode 100644 index 00000000000..e2db5ad1f43 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-6a.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom" } */ +/* { dg-final { scan-assembler-times "nop" 4 } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +int +foo (int x, int y) +{ + return x + y; +} diff --git a/gcc/testsuite/gcc.target/i386/pad-6b.c b/gcc/testsuite/gcc.target/i386/pad-6b.c new file mode 100644 index 00000000000..d8f9bec5d4f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-6b.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom" } */ +/* { dg-final { scan-assembler-times "nop" 6 } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +int +foo (int x, int y) +{ + return x + y; +} diff --git a/gcc/testsuite/gcc.target/i386/pad-7.c b/gcc/testsuite/gcc.target/i386/pad-7.c new file mode 100644 index 00000000000..8904eca0bc7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-7.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom" } */ +/* { dg-final { scan-assembler-not "nop" } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +int +foo (int x, int y, int z) +{ + return x + y + z + y; +} diff --git a/gcc/testsuite/gcc.target/i386/pad-8.c b/gcc/testsuite/gcc.target/i386/pad-8.c new file mode 100644 index 00000000000..0e939fa7890 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-8.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom" } */ +/* { dg-final { scan-assembler-times "nop" 6 } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +int +foo (int x, int y) +{ + return y; +} diff --git a/gcc/testsuite/gcc.target/i386/pad-9.c b/gcc/testsuite/gcc.target/i386/pad-9.c new file mode 100644 index 00000000000..69e33446b75 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pad-9.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O2 -fomit-frame-pointer -march=atom" } */ +/* { dg-final { scan-assembler-times "nop" 4 } } */ +/* { dg-final { scan-assembler-not "rep" } } */ + +extern void bar (void); + +void +foo (int x) +{ + if (x) + bar (); +} diff --git a/gcc/testsuite/gcc.target/i386/pr36502.c b/gcc/testsuite/gcc.target/i386/pr36502.c index 5794159d8e7..bc4c7ccf1c8 100644 --- a/gcc/testsuite/gcc.target/i386/pr36502.c +++ b/gcc/testsuite/gcc.target/i386/pr36502.c @@ -1,6 +1,6 @@ /* PR target/36502 */ /* { dg-do compile { target { *-*-darwin* && ilp32 } } } */ -/* { dg-options "-O -fomit-frame-pointer -fno-pic -S" } */ +/* { dg-options "-O -fomit-frame-pointer -fno-pic" } */ int a; void f() {a++;} /* { dg-final { scan-assembler-not "esp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr45234.c b/gcc/testsuite/gcc.target/i386/pr45234.c new file mode 100644 index 00000000000..b11096b65e2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr45234.c @@ -0,0 +1,18 @@ +/* PR middle-end/45234 */ +/* { dg-do compile } */ +/* { dg-options "-march=i586" { target ilp32 } } */ + +struct S { union { double b[4]; } a[18]; } s, a[5]; +void foo (struct S); +struct S bar (struct S, struct S *, struct S); + +void +foo (struct S arg) +{ +} + +void +baz (void) +{ + foo (bar (s, &a[1], a[2])); +} diff --git a/gcc/testsuite/gcc.target/i386/pr45739.c b/gcc/testsuite/gcc.target/i386/pr45739.c new file mode 100644 index 00000000000..bb36318a51c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr45739.c @@ -0,0 +1,24 @@ +/* PR rtl-optimization/45739 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse2" } */ + +#include <emmintrin.h> + +__m128i var; + +void +foo (void) +{ + __m128i zero = _mm_setzero_si128 (); + var = _mm_xor_si128 (zero, var); +} + +void +bar (void) +{ + __m128i zero = _mm_setzero_si128 (); + var = _mm_or_si128 (var, zero); +} + +/* { dg-final { scan-assembler-not "pxor\[^\n\]*xmm" } } */ +/* { dg-final { scan-assembler-not "por\[^\n\]*xmm" } } */ diff --git a/gcc/testsuite/gcc.target/i386/zee.c b/gcc/testsuite/gcc.target/i386/zee.c index 4ed3aa87b9f..b46e890e2b0 100644 --- a/gcc/testsuite/gcc.target/i386/zee.c +++ b/gcc/testsuite/gcc.target/i386/zee.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target lp64 } */ -/* { dg-options "-O2 -fzee -S" } */ +/* { dg-options "-O2 -fzee" } */ /* { dg-final { scan-assembler-not "mov\[\\t \]+\(%\[\^,\]+\),\[\\t \]*\\1" } } */ int mask[100]; int foo(unsigned x) diff --git a/gcc/testsuite/gcc.target/sparc/mnofpu.c b/gcc/testsuite/gcc.target/sparc/mnofpu.c new file mode 100644 index 00000000000..351585dd710 --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/mnofpu.c @@ -0,0 +1,90 @@ +/* PR target/35664 */ +/* Tetstcase by Mike Stein <mstein.lists@googlemail.com> */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-fpu" } */ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; +struct pt_regs { +}; +static inline __attribute__((always_inline)) struct task_struct *__get_current(void) +{ +} +static inline __attribute__((always_inline)) u32 flip_dword (u32 l) +{ + return ((l&0xff)<<24) | (((l>>8)&0xff)<<16) | (((l>>16)&0xff)<<8)| ((l>>24)&0xff); +} +static inline __attribute__((always_inline)) u32 __readl(const volatile void *addr) +{ + return flip_dword(*( volatile u32 *)addr); +} +enum e1e_registers { + E1000_PRC64 = 0x0405C, + E1000_PRC127 = 0x04060, + E1000_PRC255 = 0x04064, + E1000_PTC511 = 0x040E4, + E1000_PTC1023 = 0x040E8, + E1000_PTC1522 = 0x040EC, + E1000_MPTC = 0x040F0, +}; +enum e1000_media_type { + e1000_media_type_copper = 1, +}; +struct e1000_rx_desc { + struct { + } wb; +}; +struct e1000_hw_stats { + u64 prc64; + u64 prc127; + u64 prc255; + u64 ptc511; + u64 ptc1023; + u64 ptc1522; + u64 mptc; +}; +struct e1000_shadow_ram { + u16 value; +}; +struct e1000_dev_spec_ich8lan { + struct e1000_shadow_ram shadow_ram[2048]; +}; +struct e1000_hw { + u8 *hw_addr; + union { + struct e1000_dev_spec_ich8lan ich8lan; + } dev_spec; + enum e1000_media_type media_type; +}; +struct e1000_adapter { + u16 link_speed; + struct e1000_hw hw; + struct e1000_hw_stats stats; + unsigned int flags; +}; +static inline __attribute__((always_inline)) u32 __er32(struct e1000_hw *hw, unsigned long reg) +{ + return __readl(hw->hw_addr + reg); +} +void e1000e_update_stats(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u16 phy_tmp; + if (adapter->flags & (1 << 10)) { + adapter->stats.prc64 += __er32(hw, E1000_PRC64); + adapter->stats.prc127 += __er32(hw, E1000_PRC127); + adapter->stats.prc255 += __er32(hw, E1000_PRC255); + adapter->stats.ptc511 += __er32(hw, E1000_PTC511); + adapter->stats.ptc1023 += __er32(hw, E1000_PTC1023); + adapter->stats.ptc1522 += __er32(hw, E1000_PTC1522); + } + adapter->stats.mptc += __er32(hw, E1000_MPTC); + if (hw->media_type == e1000_media_type_copper) { + if ((adapter->link_speed == 1000) && + (!e1e_rphy(hw, 0x0A, &phy_tmp))) { + } + } +} diff --git a/gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 b/gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 index c33ad13b8c5..1f0864ba371 100644 --- a/gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 +++ b/gcc/testsuite/gfortran.dg/allocatable_dummy_2.f90 @@ -16,13 +16,13 @@ contains subroutine init2(x) integer, allocatable, intent(in) :: x(:) - allocate(x(3)) ! { dg-error "Cannot allocate" } + allocate(x(3)) ! { dg-error "variable definition context" } end subroutine init2 subroutine kill(x) integer, allocatable, intent(in) :: x(:) - deallocate(x) ! { dg-error "Cannot deallocate" } + deallocate(x) ! { dg-error "variable definition context" } end subroutine kill end program alloc_dummy diff --git a/gcc/testsuite/gfortran.dg/allocate_alloc_opt_2.f90 b/gcc/testsuite/gfortran.dg/allocate_alloc_opt_2.f90 index b6d6ca5acb1..a52b71e4984 100644 --- a/gcc/testsuite/gfortran.dg/allocate_alloc_opt_2.f90 +++ b/gcc/testsuite/gfortran.dg/allocate_alloc_opt_2.f90 @@ -6,7 +6,7 @@ subroutine sub(i, j, err) integer, intent(in), allocatable :: i(:) integer, allocatable :: m(:) integer n - allocate(i(2)) ! { dg-error "Cannot allocate" "" } - allocate(m(2), stat=j) ! { dg-error "cannot be" "" } - allocate(m(2),stat=n,errmsg=err) ! { dg-error "cannot be" "" } + allocate(i(2)) ! { dg-error "variable definition context" } + allocate(m(2), stat=j) ! { dg-error "variable definition context" } + allocate(m(2),stat=n,errmsg=err) ! { dg-error "variable definition context" } end subroutine sub diff --git a/gcc/testsuite/gfortran.dg/associate_5.f03 b/gcc/testsuite/gfortran.dg/associate_5.f03 index 31cc144d5a9..64345d323f3 100644 --- a/gcc/testsuite/gfortran.dg/associate_5.f03 +++ b/gcc/testsuite/gfortran.dg/associate_5.f03 @@ -18,9 +18,26 @@ PROGRAM main ptr => a ! { dg-error "neither TARGET nor POINTER" } END ASSOCIATE - ASSOCIATE (a => 5, & ! { dg-error "variable definition context" } - b => arr((/ 1, 3 /))) ! { dg-error "variable definition context" } - a = 4 - b = 7 + ASSOCIATE (a => 5, b => arr((/ 1, 3 /))) + a = 4 ! { dg-error "variable definition context" } + b = 7 ! { dg-error "variable definition context" } + CALL test2 (a) ! { dg-error "variable definition context" } + CALL test2 (b) ! { dg-error "variable definition context" } END ASSOCIATE + +CONTAINS + + SUBROUTINE test (x) + INTEGER, INTENT(IN) :: x + ASSOCIATE (y => x) ! { dg-error "variable definition context" } + y = 5 ! { dg-error "variable definition context" } + CALL test2 (x) ! { dg-error "variable definition context" } + END ASSOCIATE + END SUBROUTINE test + + ELEMENTAL SUBROUTINE test2 (x) + INTEGER, INTENT(OUT) :: x + x = 5 + END SUBROUTINE test2 + END PROGRAM main diff --git a/gcc/testsuite/gfortran.dg/c_sizeof_1.f90 b/gcc/testsuite/gfortran.dg/c_sizeof_1.f90 index b30bdc5285e..e0ac06f940e 100644 --- a/gcc/testsuite/gfortran.dg/c_sizeof_1.f90 +++ b/gcc/testsuite/gfortran.dg/c_sizeof_1.f90 @@ -1,7 +1,7 @@ ! { dg-do run } ! Support F2008's c_sizeof() ! -use iso_c_binding, only: c_int, c_char, c_ptr, c_intptr_t, c_null_ptr +use iso_c_binding, only: c_int, c_char, c_ptr, c_intptr_t, c_null_ptr, c_sizeof integer(kind=c_int) :: i, j(10) character(kind=c_char,len=4),parameter :: str(1) = "abcd" diff --git a/gcc/testsuite/gfortran.dg/c_sizeof_2.f90 b/gcc/testsuite/gfortran.dg/c_sizeof_2.f90 index fb65adce5f0..e163797470f 100644 --- a/gcc/testsuite/gfortran.dg/c_sizeof_2.f90 +++ b/gcc/testsuite/gfortran.dg/c_sizeof_2.f90 @@ -2,8 +2,8 @@ ! { dg-options "-std=f2003 -Wall -Wno-conversion" } ! Support F2008's c_sizeof() ! -USE ISO_C_BINDING +USE ISO_C_BINDING, only: C_SIZE_T, c_sizeof ! { dg-error "new in Fortran 2008" } integer(C_SIZE_T) :: i -i = c_sizeof(i) ! { dg-warning "Fortran 2008" } +i = c_sizeof(i) end diff --git a/gcc/testsuite/gfortran.dg/c_sizeof_3.f90 b/gcc/testsuite/gfortran.dg/c_sizeof_3.f90 new file mode 100644 index 00000000000..8a68cb94c30 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c_sizeof_3.f90 @@ -0,0 +1,18 @@ +! { dg-do link } +! +! PR fortran/40568 +! +! Module checks for C_SIZEOF (part of ISO_C_BINDING) +! +subroutine test +use iso_c_binding, only: foo => c_sizeof, bar=> c_sizeof, c_sizeof, c_int +integer(c_int) :: i +print *, c_sizeof(i), bar(i), foo(i) +end + +use iso_c_binding +implicit none +integer(c_int) :: i +print *, c_sizeof(i) +call test() +end diff --git a/gcc/testsuite/gfortran.dg/c_sizeof_4.f90 b/gcc/testsuite/gfortran.dg/c_sizeof_4.f90 new file mode 100644 index 00000000000..16172f05f5e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c_sizeof_4.f90 @@ -0,0 +1,10 @@ +! { dg-do link } +! +! PR fortran/40568 +! +! Module checks for C_SIZEOF (part of ISO_C_BINDING) +! + +implicit none +intrinsic c_sizeof ! { dg-error "does not exist" } +end diff --git a/gcc/testsuite/gfortran.dg/char_expr_2.f90 b/gcc/testsuite/gfortran.dg/char_expr_2.f90 index 86499eb454c..f3bfb04b2c8 100644 --- a/gcc/testsuite/gfortran.dg/char_expr_2.f90 +++ b/gcc/testsuite/gfortran.dg/char_expr_2.f90 @@ -11,5 +11,5 @@ interface end subroutine foo end interface character :: n(5) -call foo( (n) ) ! { dg-error "must be definable" } +call foo( (n) ) ! { dg-error "Non-variable expression" } end diff --git a/gcc/testsuite/gfortran.dg/deallocate_alloc_opt_2.f90 b/gcc/testsuite/gfortran.dg/deallocate_alloc_opt_2.f90 index 0c3e8694a6c..0df75825195 100644 --- a/gcc/testsuite/gfortran.dg/deallocate_alloc_opt_2.f90 +++ b/gcc/testsuite/gfortran.dg/deallocate_alloc_opt_2.f90 @@ -6,7 +6,7 @@ subroutine sub(i, j, err) integer, intent(in), allocatable :: i(:) integer, allocatable :: m(:) integer n - deallocate(i) ! { dg-error "Cannot deallocate" "" } - deallocate(m, stat=j) ! { dg-error "cannot be" "" } - deallocate(m,stat=n,errmsg=err) ! { dg-error "cannot be" "" } + deallocate(i) ! { dg-error "variable definition context" } + deallocate(m, stat=j) ! { dg-error "variable definition context" } + deallocate(m,stat=n,errmsg=err) ! { dg-error "variable definition context" } end subroutine sub diff --git a/gcc/testsuite/gfortran.dg/dependency_36.f90 b/gcc/testsuite/gfortran.dg/dependency_36.f90 new file mode 100644 index 00000000000..f3c0ef760f4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/dependency_36.f90 @@ -0,0 +1,28 @@ +! { dg-do compile } +! { dg-options "-O -Warray-temporaries" } +! PR 45744 - this used to ICE because of type mismatch +! in the generated temporary. +MODULE m +CONTAINS + FUNCTION rnd(n) + INTEGER, INTENT(in) :: n + REAL(8), DIMENSION(n) :: rnd + CALL RANDOM_NUMBER(rnd) + END FUNCTION rnd + + SUBROUTINE GeneticOptimize(n) + INTEGER :: n + LOGICAL :: mask(n) + REAL(8) :: popcross=0 + REAL(4) :: foo(n) + real(4) :: a(n,n), b(n,n) + real(8) :: c(n,n) + integer(4) :: x(n,n) + integer(8) :: bar(n) + mask = (rnd(n) < popcross) ! { dg-warning "Creating array temporary" } + foo = rnd(n) ! { dg-warning "Creating array temporary" } + bar = rnd(n) ! { dg-warning "Creating array temporary" } + c = matmul(a,b) ! { dg-warning "Creating array temporary" } + x = matmul(a,b) ! { dg-warning "Creating array temporary" } + END SUBROUTINE GeneticOptimize +END MODULE m diff --git a/gcc/testsuite/gfortran.dg/derived_array_intrinisics_1.f90 b/gcc/testsuite/gfortran.dg/derived_array_intrinisics_1.f90 new file mode 100644 index 00000000000..07d89854eb7 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/derived_array_intrinisics_1.f90 @@ -0,0 +1,30 @@ +! { dg-do compile } +! { dg-options "-fdump-tree-original" } +! Test the fix for PR45081 in which derived type array valued intrinsics failed +! to simplify, which caused an ICE in trans-array.c +! +! Contributed by Thorsten Ohl <ohl@physik.uni-wuerzburg.de> +! + module m + implicit none + integer :: i + type t + integer :: i + end type t + type(t), dimension(4), parameter :: t1 = [( t(i), i = 1, 4)] + type(t), dimension(4), parameter :: t2 = [( t(i), i = 8, 11)] + type(t), dimension(2,2), parameter :: a = reshape ( t1, [ 2, 2 ] ) + type(t), dimension(2,2), parameter :: b = transpose (a) + type(t), dimension(4), parameter :: c = reshape ( b, [ 4 ] ) + type(t), dimension(2), parameter :: d = pack ( c, [.false.,.true.,.false.,.true.]) + type(t), dimension(4), parameter :: e = unpack (d, [.false.,.true.,.false.,.true.], t2) + type(t), dimension(4,2), parameter :: f = spread (e, 2, 2) + type(t), dimension(8), parameter :: g = reshape ( f, [ 8 ] ) + integer, parameter :: total = sum(g%i) + end module m + + use m + integer :: j + j = total + end +! { dg-final { scan-tree-dump-times "j = 50" 1 "original" } } diff --git a/gcc/testsuite/gfortran.dg/enum_2.f90 b/gcc/testsuite/gfortran.dg/enum_2.f90 index 6d8a4b22b24..8f7aea1f02e 100644 --- a/gcc/testsuite/gfortran.dg/enum_2.f90 +++ b/gcc/testsuite/gfortran.dg/enum_2.f90 @@ -9,5 +9,7 @@ program main enumerator blue = 1 ! { dg-error "Syntax error in ENUMERATOR definition" } end enum + red = 42 ! { dg-error "variable definition context" } + enumerator :: sun ! { dg-error "ENUM" } end program main diff --git a/gcc/testsuite/gfortran.dg/enum_5.f90 b/gcc/testsuite/gfortran.dg/enum_5.f90 index c5617b8c1ba..81a1dd5dfa4 100644 --- a/gcc/testsuite/gfortran.dg/enum_5.f90 +++ b/gcc/testsuite/gfortran.dg/enum_5.f90 @@ -10,7 +10,7 @@ program main enumerator :: blue = 1 end enum junk ! { dg-error "Syntax error" } - blue = 10 ! { dg-error " assign to a named constant" } + blue = 10 ! { dg-error "Unexpected assignment" } end program main ! { dg-error "Expecting END ENUM" } ! { dg-error "Unexpected end of file" "" { target "*-*-*" } 0 } diff --git a/gcc/testsuite/gfortran.dg/equiv_constraint_8.f90 b/gcc/testsuite/gfortran.dg/equiv_constraint_8.f90 index 9a742eec5c4..1cb28b0318f 100644 --- a/gcc/testsuite/gfortran.dg/equiv_constraint_8.f90 +++ b/gcc/testsuite/gfortran.dg/equiv_constraint_8.f90 @@ -9,7 +9,7 @@ pure integer function test(j) common /z/ i integer :: k equivalence(i,k) ! { dg-error "EQUIVALENCE object in the pure" } - k=1 ! { dg-error "in PURE procedure at" } + k=1 ! { dg-error "variable definition context" } test=i*j end function test end diff --git a/gcc/testsuite/gfortran.dg/impure_assignment_2.f90 b/gcc/testsuite/gfortran.dg/impure_assignment_2.f90 index 3b212c19897..6378ec8a47b 100644 --- a/gcc/testsuite/gfortran.dg/impure_assignment_2.f90 +++ b/gcc/testsuite/gfortran.dg/impure_assignment_2.f90 @@ -23,7 +23,7 @@ CONTAINS TYPE(node_type), POINTER :: node TYPE(node_type), POINTER :: give_next give_next => node%next ! { dg-error "Bad target" } - node%next => give_next ! { dg-error "Bad pointer object" } + node%next => give_next ! { dg-error "variable definition context" } END FUNCTION ! Comment #2 PURE integer FUNCTION give_next2(i) @@ -55,14 +55,14 @@ CONTAINS TYPE(T1), POINTER :: RES RES => A ! { dg-error "Bad target" } RES => B ! { dg-error "Bad target" } - B => RES ! { dg-error "Bad pointer object" } + B => RES ! { dg-error "variable definition context" } END FUNCTION PURE FUNCTION TST2(A) RESULT(RES) TYPE(T1), INTENT(IN), TARGET :: A TYPE(T1), POINTER :: RES allocate (RES) RES = A - B = RES ! { dg-error "Cannot assign" } + B = RES ! { dg-error "variable definition context" } RES = B END FUNCTION END MODULE pr20882 diff --git a/gcc/testsuite/gfortran.dg/impure_assignment_3.f90 b/gcc/testsuite/gfortran.dg/impure_assignment_3.f90 index 462ceb64d93..8be19896ef5 100644 --- a/gcc/testsuite/gfortran.dg/impure_assignment_3.f90 +++ b/gcc/testsuite/gfortran.dg/impure_assignment_3.f90 @@ -20,7 +20,7 @@ contains class is (myType) x%a = 42. r3 = 43. - g = 44. ! { dg-error "Cannot assign to variable" } + g = 44. ! { dg-error "variable definition context" } end select end subroutine @@ -30,7 +30,7 @@ contains real :: r2 r1 = 45. r2 = 46. - g = 47. ! { dg-error "Cannot assign to variable" } + g = 47. ! { dg-error "variable definition context" } end block end subroutine diff --git a/gcc/testsuite/gfortran.dg/inline_transpose_1.f90 b/gcc/testsuite/gfortran.dg/inline_transpose_1.f90 index 50290c6fad1..a364842517c 100644 --- a/gcc/testsuite/gfortran.dg/inline_transpose_1.f90 +++ b/gcc/testsuite/gfortran.dg/inline_transpose_1.f90 @@ -61,10 +61,10 @@ if (u /= v) call abort - a = foo(transpose(c)) ! Unnecessary { dg-warning "Creating array temporary" } + a = foo(transpose(c)) if (any(a /= p+1)) call abort - write(u,*) foo(transpose(c)) ! 2 temps, should be 1 { dg-warning "Creating array temporary" } + write(u,*) foo(transpose(c)) ! { dg-warning "Creating array temporary" } write(v,*) p+1 if (u /= v) call abort @@ -77,10 +77,10 @@ if (u /= v) call abort - e = foo(transpose(e)) ! 2 temps, should be 1 { dg-warning "Creating array temporary" } + e = foo(transpose(e)) ! { dg-warning "Creating array temporary" } if (any(e /= 2*s+1)) call abort - write(u,*) transpose(foo(transpose(e))-1) ! 2 temps, should be 1 { dg-warning "Creating array temporary" } + write(u,*) transpose(foo(transpose(e))-1) ! { dg-warning "Creating array temporary" } write(v,*) 2*s+1 if (u /= v) call abort @@ -141,28 +141,46 @@ if (u /= v) call abort - if (any(transpose(matmul(a,c)) /= matmul(transpose(c), transpose(a)))) call abort ! 4 temps, should be 2 { dg-warning "Creating array temporary" } + if (any(transpose(matmul(a,c)) /= matmul(transpose(c), transpose(a)))) call abort ! 2 temps { dg-warning "Creating array temporary" } write(u,*) transpose(matmul(a,c)) ! { dg-warning "Creating array temporary" } - write(v,*) matmul(transpose(c), transpose(a)) ! 3 temps, should be 1 { dg-warning "Creating array temporary" } + write(v,*) matmul(transpose(c), transpose(a)) ! { dg-warning "Creating array temporary" } if (u /= v) call abort - if (any(transpose(matmul(e,a)) /= matmul(transpose(a), transpose(e)))) call abort ! 4 temps, should be 2 { dg-warning "Creating array temporary" } + if (any(transpose(matmul(e,a)) /= matmul(transpose(a), transpose(e)))) call abort ! 2 temps { dg-warning "Creating array temporary" } write(u,*) transpose(matmul(e,a)) ! { dg-warning "Creating array temporary" } - write(v,*) matmul(transpose(a), transpose(e)) ! 3 temps, should be 1 { dg-warning "Creating array temporary" } + write(v,*) matmul(transpose(a), transpose(e)) ! { dg-warning "Creating array temporary" } if (u /= v) call abort - call baz (transpose(a)) ! Unnecessary { dg-warning "Creating array temporary" } + call baz (transpose(a)) - call toto (f, transpose (e)) - if (any (f /= 4 * s + 12)) call abort - call toto (f, transpose (f)) ! { dg-warning "Creating array temporary" } - if (any (f /= 8 * r + 24)) call abort + call toto1 (a, transpose (c)) + if (any (a /= 2 * p + 12)) call abort + call toto1 (e, transpose (e)) ! { dg-warning "Creating array temporary" } + if (any (e /= 4 * s + 12)) call abort + + + call toto2 (c, transpose (a)) + if (any (c /= 2 * q + 13)) call abort + + call toto2 (e, transpose(e)) ! { dg-warning "Creating array temporary" } + if (any (e /= 4 * r + 13)) call abort + + call toto2 (e, transpose(transpose(e))) ! { dg-warning "Creating array temporary" } + if (any (e /= 4 * r + 14)) call abort + + + call toto3 (e, transpose(e)) + if (any (e /= 4 * r + 14)) call abort + + + call titi (nx, e, transpose(e)) ! { dg-warning "Creating array temporary" } + if (any (e /= 4 * s + 17)) call abort contains @@ -182,23 +200,39 @@ integer, intent(in) :: x(:,:) end subroutine baz - elemental subroutine toto (x, y) + elemental subroutine toto1 (x, y) integer, intent(out) :: x integer, intent(in) :: y x = y + y - end subroutine toto + end subroutine toto1 + + subroutine toto2 (x, y) + integer, dimension(:,:), intent(out) :: x + integer, dimension(:,:), intent(in) :: y + x = y + 1 + end subroutine toto2 + + subroutine toto3 (x, y) + integer, dimension(:,:), intent(in) :: x, y + end subroutine toto3 end + +subroutine titi (n, x, y) + integer :: n, x(n,n), y(n,n) + x = y + 3 +end subroutine titi + ! No call to transpose ! { dg-final { scan-tree-dump-times "_gfortran_transpose" 0 "original" } } ! -! 34 temporaries -! { dg-final { scan-tree-dump-times "struct\[^\\n\]*atmp" 34 "original" } } +! 24 temporaries +! { dg-final { scan-tree-dump-times "struct\[^\\n\]*atmp" 24 "original" } } ! ! 2 tests optimized out -! { dg-final { scan-tree-dump-times "_gfortran_abort" 34 "original" } } -! { # Commented out as failing at -O0: dg-final { scan-tree-dump-times "_gfortran_abort" 32 "optimized" } } +! { dg-final { scan-tree-dump-times "_gfortran_abort" 39 "original" } } +! { # Commented out as failing at -O0: dg-final { scan-tree-dump-times "_gfortran_abort" 37 "optimized" } } ! ! cleanup -! { #dg-final { cleanup-tree-dump "original" } } +! { dg-final { cleanup-tree-dump "original" } } ! { dg-final { cleanup-tree-dump "optimized" } } diff --git a/gcc/testsuite/gfortran.dg/intent_out_1.f90 b/gcc/testsuite/gfortran.dg/intent_out_1.f90 index 62d74157302..98338bf47ad 100644 --- a/gcc/testsuite/gfortran.dg/intent_out_1.f90 +++ b/gcc/testsuite/gfortran.dg/intent_out_1.f90 @@ -3,10 +3,10 @@ ! Contributed by Paul Thomas <pault@gcc@gnu.org> real, parameter :: a =42.0 real :: b - call foo(b + 2.0) ! { dg-error "must be definable" } - call foo(a) ! { dg-error "must be definable" } - call bar(b + 2.0) ! { dg-error "must be definable" } - call bar(a) ! { dg-error "must be definable" } + call foo(b + 2.0) ! { dg-error "variable definition context" } + call foo(a) ! { dg-error "variable definition context" } + call bar(b + 2.0) ! { dg-error "variable definition context" } + call bar(a) ! { dg-error "variable definition context" } contains subroutine foo(a) real, intent(out) :: a diff --git a/gcc/testsuite/gfortran.dg/intent_out_3.f90 b/gcc/testsuite/gfortran.dg/intent_out_3.f90 index 7346fd04668..e3300c988f5 100644 --- a/gcc/testsuite/gfortran.dg/intent_out_3.f90 +++ b/gcc/testsuite/gfortran.dg/intent_out_3.f90 @@ -15,6 +15,6 @@ CONTAINS END SUBROUTINE S1 END MODULE M1 USE M1 -CALL S1(D1%I(3)) ! { dg-error "must be definable" } +CALL S1(D1%I(3)) ! { dg-error "variable definition context" } END ! { dg-final { cleanup-modules "m1" } } diff --git a/gcc/testsuite/gfortran.dg/intrinsic_intent_1.f03 b/gcc/testsuite/gfortran.dg/intrinsic_intent_1.f03 new file mode 100644 index 00000000000..1f39f7551a2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/intrinsic_intent_1.f03 @@ -0,0 +1,11 @@ +! { dg-do compile } + +! PR fortran/45474 +! Definability checks for INTENT([IN]OUT) and intrinsics. + +! Contributed by Tobias Burnus, burnus@gcc.gnu.org. + +call execute_command_line("date", .true.,(1),1,'aa') ! { dg-error "variable definition context" } +call execute_command_line("date", .true.,1,(1),'aa') ! { dg-error "variable definition context" } +call execute_command_line("date", .true.,1,1,('aa')) ! { dg-error "variable definition context" } +end diff --git a/gcc/testsuite/gfortran.dg/io_constraints_6.f03 b/gcc/testsuite/gfortran.dg/io_constraints_6.f03 new file mode 100644 index 00000000000..d0484f5f4fe --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_constraints_6.f03 @@ -0,0 +1,40 @@ +! { dg-do compile } + +! PR fortran/45776 +! Variable definition context checks related to IO. + +! Contributed by Daniel Kraft, d@domob.eu. + +module m + implicit none + + integer, protected :: a + character(len=128), protected :: str +end module m + +program main + use :: m + integer, parameter :: b = 42 + integer :: x + character(len=128) :: myStr + + namelist /definable/ x, myStr + namelist /undefinable/ x, a + + ! These are invalid. + read (myStr, *) a ! { dg-error "variable definition context" } + read (myStr, *) x, b ! { dg-error "variable definition context" } + write (str, *) 5 ! { dg-error "variable definition context" } + read (*, nml=undefinable) ! { dg-error "contains the symbol 'a' which may not" } + + ! These are ok. + read (str, *) x + write (myStr, *) a + write (myStr, *) b + print *, a, b + write (*, nml=undefinable) + read (*, nml=definable) + write (*, nml=definable) +end program main + +! { dg-final { cleanup-modules "m" } } diff --git a/gcc/testsuite/gfortran.dg/io_constraints_7.f03 b/gcc/testsuite/gfortran.dg/io_constraints_7.f03 new file mode 100644 index 00000000000..4d184919814 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/io_constraints_7.f03 @@ -0,0 +1,37 @@ +! { dg-do compile } + +! PR fortran/45776 +! Variable definition context checks related to IO. + +! Contributed by Daniel Kraft, d@domob.eu. + +module m + implicit none + integer, protected :: a + character(len=128), protected :: msg +end module m + +program main + use :: m + integer :: x + logical :: bool + + write (*, iostat=a) 42 ! { dg-error "variable definition context" } + write (*, iomsg=msg) 42 ! { dg-error "variable definition context" } + read (*, '(I2)', advance='no', size=a) x ! { dg-error "variable definition context" } + + ! These are ok. + inquire (unit=a) + inquire (file=msg, id=a, pending=bool) + inquire (file=msg) + + ! These not, but list is not extensive. + inquire (unit=1, number=a) ! { dg-error "variable definition context" } + inquire (unit=1, encoding=msg) ! { dg-error "variable definition context" } + inquire (unit=1, formatted=msg) ! { dg-error "variable definition context" } + + open (newunit=a, file="foo") ! { dg-error "variable definition context" } + close (unit=a) +end program main + +! { dg-final { cleanup-modules "m" } } diff --git a/gcc/testsuite/gfortran.dg/iso_c_binding_compiler_1.f90 b/gcc/testsuite/gfortran.dg/iso_c_binding_compiler_1.f90 new file mode 100644 index 00000000000..8eccb6b9e7a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/iso_c_binding_compiler_1.f90 @@ -0,0 +1,18 @@ +! { dg-do link } +! +! PR fortran/40569 +! +! Check compiler_version/compiler_options intrinsics +! +subroutine test() + use iso_fortran_env, only: compiler_version + print '(3a)', '>>',compiler_version(),'<<' +end + +use iso_fortran_env, foo => compiler_version, bar => compiler_version + implicit none + print *, foo() + print *, bar() + print '(3a)', '>',compiler_options(),'<' + call test() +end diff --git a/gcc/testsuite/gfortran.dg/iso_c_binding_compiler_2.f90 b/gcc/testsuite/gfortran.dg/iso_c_binding_compiler_2.f90 new file mode 100644 index 00000000000..279cfe60e23 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/iso_c_binding_compiler_2.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } +! +! PR fortran/40569 +! +! Check compiler_version/compiler_options intrinsics +! +use iso_fortran_env, only: compiler_options ! { dg-error "is not in the selected standard" } +use iso_fortran_env, only: compiler_version ! { dg-error "is not in the selected standard" } + implicit none +end diff --git a/gcc/testsuite/gfortran.dg/iso_fortran_env_7.f90 b/gcc/testsuite/gfortran.dg/iso_fortran_env_7.f90 new file mode 100644 index 00000000000..c8617efb169 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/iso_fortran_env_7.f90 @@ -0,0 +1,61 @@ +! { dg-do link } +! +! PR fortran/40571 +! +! This test case adds check for the new Fortran 2008 array parameters +! in ISO_FORTRAN_ENV: integer_kinds, logical_kinds, character_kinds, +! and real_kinds. +! +! The test thus also checks that the values of the parameter are used +! and no copy is made. (Cf. PR 44856.) + +program test + use iso_fortran_env, only: integer_kinds, character_kinds + implicit none + integer :: aaaa(2),i + i=1 + + print *, integer_kinds + print *, integer_kinds(1) + print *, (integer_kinds) + print *, (integer_kinds + 1) + print *, integer_kinds(1:2) + print *, integer_kinds(i) + + aaaa = character_kinds + aaaa(1:2) = character_kinds(1:2) + aaaa(i) = character_kinds(i) + aaaa = character_kinds + 0 + aaaa(1:2) = character_kinds(1:2) + 0 + aaaa(i) = character_kinds(i) + 0 +end program test + +subroutine one() + use iso_fortran_env, only: ik => integer_kinds, ik2 => integer_kinds + implicit none + + if (any (ik /= ik2)) call never_call_me() +end subroutine one + +subroutine two() + use iso_fortran_env + implicit none + + ! Should be 1, 2, 4, 8 and possibly 16 + if (size (integer_kinds) < 4) call never_call_me() + if (any (integer_kinds(1:4) /= [1,2,4,8])) call never_call_me() + if (any (integer_kinds /= logical_kinds)) call never_call_me() + + if (size (character_kinds) /= 2) call never_call_me() + if (any (character_kinds /= [1,4])) call never_call_me() + + if (size (real_kinds) < 2) call never_call_me() + if (any (real_kinds(1:2) /= [4,8])) call never_call_me() +end subroutine two + +subroutine three() + use iso_fortran_env + integer :: i, j(2) + i = real_kinds(1) + j = real_kinds(1:2) +end subroutine three diff --git a/gcc/testsuite/gfortran.dg/namelist_65.f90 b/gcc/testsuite/gfortran.dg/namelist_65.f90 new file mode 100644 index 00000000000..6ef8ca493a5 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/namelist_65.f90 @@ -0,0 +1,22 @@ +! { dg-do run } +! { dg-options "-std=gnu" } +! PR45710 Adjust format/padding for WRITE of NAMELIST group to internal file +program oneline +real :: a=1,b=2,c=3,d=4 +namelist /nl1/ a,b,c +parameter(ilines=5) +character(len=80) :: out(ilines) + +! fill array out with @ +do i=1,len(out) + out(:)(i:i)='@' +enddo + +write(out,nl1) +if (out(1).ne."&NL1") call abort +if (out(2).ne." A= 1.0000000 ,") call abort +if (out(3).ne." B= 2.0000000 ,") call abort +if (out(4).ne." C= 3.0000000 ,") call abort +if (out(5).ne." /") call abort + +end program oneline diff --git a/gcc/testsuite/gfortran.dg/newunit_2.f90 b/gcc/testsuite/gfortran.dg/newunit_2.f90 new file mode 100644 index 00000000000..b0f797a0736 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/newunit_2.f90 @@ -0,0 +1,15 @@ +! { dg-do compile } +! { dg-options "-std=f95" } + +! PR40008 F2008: Add NEWUNIT= for OPEN statement +! Check for rejection with pre-F2008 standard. + +! Contributed by Daniel Kraft, d@domob.eu. + +program main + character(len=25) :: str + integer(1) :: myunit + + open (newunit=myunit, file="some_file") ! { dg-error "Fortran 2008" } + close (unit=myunit) +end program main diff --git a/gcc/testsuite/gfortran.dg/operator_c1202.f90 b/gcc/testsuite/gfortran.dg/operator_c1202.f90 new file mode 100644 index 00000000000..c53079ac5d8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/operator_c1202.f90 @@ -0,0 +1,68 @@ +! { dg-do compile } +module op + + implicit none + + type a + integer i + end type a + + type b + real i + end type b + + interface operator(==) + module procedure f1 + end interface operator(.eq.) + interface operator(.eq.) + module procedure f2 + end interface operator(==) + + interface operator(/=) + module procedure f1 + end interface operator(.ne.) + interface operator(.ne.) + module procedure f2 + end interface operator(/=) + + interface operator(<=) + module procedure f1 + end interface operator(.le.) + interface operator(.le.) + module procedure f2 + end interface operator(<=) + + interface operator(<) + module procedure f1 + end interface operator(.lt.) + interface operator(.lt.) + module procedure f2 + end interface operator(<) + + interface operator(>=) + module procedure f1 + end interface operator(.ge.) + interface operator(.ge.) + module procedure f2 + end interface operator(>=) + + interface operator(>) + module procedure f1 + end interface operator(.gt.) + interface operator(.gt.) + module procedure f2 + end interface operator(>) + + contains + + function f2(x,y) + logical f2 + type(a), intent(in) :: x, y + end function f2 + + function f1(x,y) + logical f1 + type(b), intent(in) :: x, y + end function f1 + +end module op diff --git a/gcc/testsuite/gfortran.dg/pointer_assign_7.f90 b/gcc/testsuite/gfortran.dg/pointer_assign_7.f90 index 5ec32e8d66e..c85dc72c8ff 100644 --- a/gcc/testsuite/gfortran.dg/pointer_assign_7.f90 +++ b/gcc/testsuite/gfortran.dg/pointer_assign_7.f90 @@ -18,7 +18,7 @@ type(face_t), pointer :: face allocate(face) allocate(blu) -face%bla => blu ! { dg-error "Pointer assignment to non-POINTER" } +face%bla => blu ! { dg-error "Non-POINTER in pointer association context" } end program diff --git a/gcc/testsuite/gfortran.dg/pointer_check_7.f90 b/gcc/testsuite/gfortran.dg/pointer_check_7.f90 new file mode 100644 index 00000000000..0f6dcdc87fc --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pointer_check_7.f90 @@ -0,0 +1,36 @@ +! { dg-do compile } +! { dg-options "-fcheck=pointer" } +! +! PR 45438: [4.6 Regression] [OOP] ICE with -fcheck=pointer +! +! Contributed by Salvatore Filippone <sfilippone@uniroma2.it> + +module base_mat_mod + + implicit none + + type :: base_sparse_mat + contains + procedure :: get_fmt + end type + +contains + + function get_fmt(a) result(res) + class(base_sparse_mat), intent(in) :: a + character(len=5) :: res + res = 'NULL' + end function + + subroutine errlog(name) + character(len=*) :: name + end subroutine + + subroutine test (a) + class(base_sparse_mat), intent(in) :: a + call errlog(a%get_fmt()) + end subroutine + +end module + +! { dg-final { cleanup-modules "base_mat_mod" } } diff --git a/gcc/testsuite/gfortran.dg/pointer_intent_3.f90 b/gcc/testsuite/gfortran.dg/pointer_intent_3.f90 index 04a7bc567e0..7f87d10e9bb 100644 --- a/gcc/testsuite/gfortran.dg/pointer_intent_3.f90 +++ b/gcc/testsuite/gfortran.dg/pointer_intent_3.f90 @@ -19,11 +19,11 @@ program test contains subroutine a(p) integer, pointer,intent(in) :: p - p => null(p)! { dg-error "Cannot assign to INTENT\\(IN\\) variable" } - nullify(p) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" } - allocate(p) ! { dg-error "Cannot allocate INTENT\\(IN\\) variable" } - call c(p) ! { dg-error "is INTENT\\(IN\\) while interface specifies INTENT\\(INOUT\\)" } - deallocate(p) ! { dg-error "Cannot deallocate INTENT\\(IN\\) variable" } + p => null(p)! { dg-error "pointer association context" } + nullify(p) ! { dg-error "pointer association context" } + allocate(p) ! { dg-error "pointer association context" } + call c(p) ! { dg-error "pointer association context" } + deallocate(p) ! { dg-error "pointer association context" } end subroutine subroutine c(p) integer, pointer, intent(inout) :: p @@ -32,10 +32,10 @@ contains subroutine b(t) type(myT),intent(in) :: t t%jp = 5 - t%jp => null(t%jp) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" } - nullify(t%jp) ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" } - t%j = 7 ! { dg-error "Cannot assign to INTENT\\(IN\\) variable" } - allocate(t%jp) ! { dg-error "Cannot allocate INTENT\\(IN\\) variable" } - deallocate(t%jp) ! { dg-error "Cannot deallocate INTENT\\(IN\\) variable" } + t%jp => null(t%jp) ! { dg-error "pointer association context" } + nullify(t%jp) ! { dg-error "pointer association context" } + t%j = 7 ! { dg-error "variable definition context" } + allocate(t%jp) ! { dg-error "pointer association context" } + deallocate(t%jp) ! { dg-error "pointer association context" } end subroutine b end program diff --git a/gcc/testsuite/gfortran.dg/pr19936_1.f90 b/gcc/testsuite/gfortran.dg/pr19936_1.f90 index 516d5142922..440c1d9d702 100644 --- a/gcc/testsuite/gfortran.dg/pr19936_1.f90 +++ b/gcc/testsuite/gfortran.dg/pr19936_1.f90 @@ -1,5 +1,5 @@ ! { dg-do compile } program pr19936_1 integer, parameter :: i=4 - print *,(/(i,i=1,4)/) ! { dg-error "assign to a named constant" } + print *,(/(i,i=1,4)/) ! { dg-error "variable definition context" } end program pr19936_1 diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_comp_3.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_comp_3.f90 index 4b866c0c562..67d5b536068 100644 --- a/gcc/testsuite/gfortran.dg/proc_ptr_comp_3.f90 +++ b/gcc/testsuite/gfortran.dg/proc_ptr_comp_3.f90 @@ -38,7 +38,7 @@ type(t) :: x x%ptr2 => x ! { dg-error "Invalid procedure pointer assignment" } -x => x%ptr2 ! { dg-error "Pointer assignment to non-POINTER" } +x => x%ptr2 ! { dg-error "Non-POINTER in pointer association context" } print *, x%ptr1() ! { dg-error "attribute conflicts with" } call x%ptr2() ! { dg-error "attribute conflicts with" } diff --git a/gcc/testsuite/gfortran.dg/protected_4.f90 b/gcc/testsuite/gfortran.dg/protected_4.f90 index 8e637ef3a9c..7f0e49f09a4 100644 --- a/gcc/testsuite/gfortran.dg/protected_4.f90 +++ b/gcc/testsuite/gfortran.dg/protected_4.f90 @@ -23,15 +23,15 @@ program main integer :: j logical :: asgnd protected :: j ! { dg-error "only allowed in specification part of a module" } - a = 43 ! { dg-error "Assigning to PROTECTED variable" } - ap => null() ! { dg-error "Assigning to PROTECTED variable" } - nullify(ap) ! { dg-error "Assigning to PROTECTED variable" } - ap => at ! { dg-error "Assigning to PROTECTED variable" } - ap = 3 ! { dg-error "Assigning to PROTECTED variable" } - allocate(ap) ! { dg-error "Assigning to PROTECTED variable" } - ap = 73 ! { dg-error "Assigning to PROTECTED variable" } - call increment(a,at) ! { dg-error "use-associated with PROTECTED attribute" } - call pointer_assignments(ap) ! { dg-error "is use-associated with PROTECTED attribute" } + a = 43 ! { dg-error "variable definition context" } + ap => null() ! { dg-error "pointer association context" } + nullify(ap) ! { dg-error "pointer association context" } + ap => at ! { dg-error "pointer association context" } + ap = 3 ! OK + allocate(ap) ! { dg-error "pointer association context" } + ap = 73 ! OK + call increment(a,at) ! { dg-error "variable definition context" } + call pointer_assignments(ap) ! { dg-error "pointer association context" } asgnd = pointer_check(ap) contains subroutine increment(a1,a3) diff --git a/gcc/testsuite/gfortran.dg/protected_5.f90 b/gcc/testsuite/gfortran.dg/protected_5.f90 index 2b19dfa1cef..85046c3cb9a 100644 --- a/gcc/testsuite/gfortran.dg/protected_5.f90 +++ b/gcc/testsuite/gfortran.dg/protected_5.f90 @@ -49,9 +49,9 @@ end module good2 program main use good2 implicit none - t%j = 15 ! { dg-error "Assigning to PROTECTED variable" } - nullify(t%p) ! { dg-error "Assigning to PROTECTED variable" } - allocate(t%array(15))! { dg-error "Assigning to PROTECTED variable" } + t%j = 15 ! { dg-error "variable definition context" } + nullify(t%p) ! { dg-error "pointer association context" } + allocate(t%array(15))! { dg-error "variable definition context" } end program main ! { dg-final { cleanup-modules "good1 good2 bad1 bad2" } } diff --git a/gcc/testsuite/gfortran.dg/protected_6.f90 b/gcc/testsuite/gfortran.dg/protected_6.f90 index 2cc5b8162e8..e7f3e4e9337 100644 --- a/gcc/testsuite/gfortran.dg/protected_6.f90 +++ b/gcc/testsuite/gfortran.dg/protected_6.f90 @@ -19,15 +19,15 @@ end module protmod program main use protmod implicit none - a = 43 ! { dg-error "Assigning to PROTECTED variable" } - ap => null() ! { dg-error "Assigning to PROTECTED variable" } - nullify(ap) ! { dg-error "Assigning to PROTECTED variable" } - ap => at ! { dg-error "Assigning to PROTECTED variable" } - ap = 3 ! { dg-error "Assigning to PROTECTED variable" } - allocate(ap) ! { dg-error "Assigning to PROTECTED variable" } - ap = 73 ! { dg-error "Assigning to PROTECTED variable" } - call increment(a,at) ! { dg-error "use-associated with PROTECTED attribute" } - call pointer_assignments(ap) ! { dg-error "is use-associated with PROTECTED attribute" } + a = 43 ! { dg-error "variable definition context" } + ap => null() ! { dg-error "pointer association context" } + nullify(ap) ! { dg-error "pointer association context" } + ap => at ! { dg-error "pointer association context" } + ap = 3 ! OK + allocate(ap) ! { dg-error "pointer association context" } + ap = 73 ! OK + call increment(a,at) ! { dg-error "variable definition context" } + call pointer_assignments(ap) ! { dg-error "pointer association context" } contains subroutine increment(a1,a3) integer, intent(inout) :: a1, a3 diff --git a/gcc/testsuite/gfortran.dg/protected_7.f90 b/gcc/testsuite/gfortran.dg/protected_7.f90 index 0325a49a568..abdc9592aaf 100644 --- a/gcc/testsuite/gfortran.dg/protected_7.f90 +++ b/gcc/testsuite/gfortran.dg/protected_7.f90 @@ -13,8 +13,8 @@ program p integer, pointer :: unprotected_pointer ! The next two lines should be rejected; see PR 37513 why ! we get such a strange error message. - protected_pointer => unprotected_pointer ! { dg-error "only allowed in specification part" } - protected_pointer = unprotected_pointer ! { dg-error "only allowed in specification part" } + protected_pointer => unprotected_pointer ! { dg-error "pointer association context" } + protected_pointer = unprotected_pointer ! OK unprotected_pointer => protected_target ! { dg-error "target has PROTECTED attribute" } unprotected_pointer => protected_pointer ! OK end program p diff --git a/gcc/testsuite/gfortran.dg/select_type_17.f03 b/gcc/testsuite/gfortran.dg/select_type_17.f03 new file mode 100644 index 00000000000..af2a489d971 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/select_type_17.f03 @@ -0,0 +1,44 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } + +! PR fortran/44044 +! Definability check for select type to expression. +! This is "bonus feature #2" from comment #3 of the PR. + +! Contributed by Janus Weil, janus@gcc.gnu.org. + +implicit none + +type :: t1 + integer :: i +end type + +type, extends(t1) :: t2 +end type + +type(t1),target :: x1 +type(t2),target :: x2 + +select type ( y => fun(1) ) +type is (t1) + y%i = 1 ! { dg-error "variable definition context" } +type is (t2) + y%i = 2 ! { dg-error "variable definition context" } +end select + +contains + + function fun(i) + class(t1),pointer :: fun + integer :: i + if (i>0) then + fun => x1 + else if (i<0) then + fun => x2 + else + fun => NULL() + end if + end function + +end + diff --git a/gcc/testsuite/gfortran.dg/select_type_18.f03 b/gcc/testsuite/gfortran.dg/select_type_18.f03 new file mode 100644 index 00000000000..e4bacd377e7 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/select_type_18.f03 @@ -0,0 +1,90 @@ +! { dg-do compile } + +! PR fortran/45783 +! PR fortran/45795 +! This used to fail because of incorrect compile-time typespec on the +! SELECT TYPE selector. + +! This is the test-case from PR 45795. +! Contributed by Salvatore Filippone, sfilippone@uniroma2.it. + +module base_mod + + type :: base + integer :: m, n + end type base + +end module base_mod + +module s_base_mod + + use base_mod + + type, extends(base) :: s_base + contains + procedure, pass(a) :: cp_to_foo => s_base_cp_to_foo + + end type s_base + + + type, extends(s_base) :: s_foo + + integer :: nnz + integer, allocatable :: ia(:), ja(:) + real, allocatable :: val(:) + + contains + + procedure, pass(a) :: cp_to_foo => s_cp_foo_to_foo + + end type s_foo + + + interface + subroutine s_base_cp_to_foo(a,b,info) + import :: s_base, s_foo + class(s_base), intent(in) :: a + class(s_foo), intent(inout) :: b + integer, intent(out) :: info + end subroutine s_base_cp_to_foo + end interface + + interface + subroutine s_cp_foo_to_foo(a,b,info) + import :: s_foo + class(s_foo), intent(in) :: a + class(s_foo), intent(inout) :: b + integer, intent(out) :: info + end subroutine s_cp_foo_to_foo + end interface + +end module s_base_mod + + +subroutine trans2(a,b) + use s_base_mod + implicit none + + class(s_base), intent(out) :: a + class(base), intent(in) :: b + + type(s_foo) :: tmp + integer err_act, info + + + info = 0 + select type(b) + class is (s_base) + call b%cp_to_foo(tmp,info) + class default + info = -1 + write(*,*) 'Invalid dynamic type' + end select + + if (info /= 0) write(*,*) 'Error code ',info + + return + +end subroutine trans2 + +! { dg-final { cleanup-modules "base_mod s_base_mod" } } diff --git a/gcc/testsuite/gfortran.dg/simpleif_2.f90 b/gcc/testsuite/gfortran.dg/simpleif_2.f90 index ee914b2c6fd..09c0d380416 100644 --- a/gcc/testsuite/gfortran.dg/simpleif_2.f90 +++ b/gcc/testsuite/gfortran.dg/simpleif_2.f90 @@ -10,6 +10,6 @@ module read subroutine a integer, parameter :: n = 2 if (i .eq. 0) read(j,*) k - if (i .eq. 0) n = j ! { dg-error "assign to a named constant" "" } + if (i .eq. 0) n = j ! { dg-error "Named constant 'n' in variable definition context" } end subroutine a end module read diff --git a/gcc/testsuite/gfortran.dg/storage_size_2.f08 b/gcc/testsuite/gfortran.dg/storage_size_2.f08 index 50de9575e74..c18155e72bd 100644 --- a/gcc/testsuite/gfortran.dg/storage_size_2.f08 +++ b/gcc/testsuite/gfortran.dg/storage_size_2.f08 @@ -4,7 +4,7 @@ ! ! Contributed by Janus Weil <janus@gcc.gnu.org> -use iso_c_binding, only: c_int +use iso_c_binding, only: c_int, c_sizeof type, bind(c) :: t integer(c_int) :: j diff --git a/gcc/testsuite/gfortran.dg/transpose_optimization_1.f90 b/gcc/testsuite/gfortran.dg/transpose_optimization_1.f90 new file mode 100644 index 00000000000..885ff7c2034 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/transpose_optimization_1.f90 @@ -0,0 +1,106 @@ +! { dg-do compile } +! { dg-options "-Warray-temporaries -fdump-tree-original" } +! +! PR fortran/45648 +! Non-copying descriptor transpose optimization (for function call args). +! +! Contributed by Richard Sandiford <richard@codesourcery.com> + +module foo + interface + subroutine ext1 (a, b) + real, intent (in), dimension (:, :) :: a, b + end subroutine ext1 + subroutine ext2 (a, b) + real, intent (in), dimension (:, :) :: a + real, intent (out), dimension (:, :) :: b + end subroutine ext2 + subroutine ext3 (a, b) + real, dimension (:, :) :: a, b + end subroutine ext3 + end interface +contains + ! No temporary needed here. + subroutine test1 (n, a, b, c) + integer :: n + real, dimension (n, n) :: a, b, c + a = matmul (transpose (b), c) + end subroutine test1 + + ! No temporary either, as we know the arguments to matmul are intent(in) + subroutine test2 (n, a, b) + integer :: n + real, dimension (n, n) :: a, b + a = matmul (transpose (b), b) + end subroutine test2 + + ! No temporary needed. + subroutine test3 (n, a, b, c) + integer :: n + real, dimension (n, n) :: a, c + real, dimension (n+4, n+4) :: b + a = matmul (transpose (b (2:n+1, 3:n+2)), c) + end subroutine test3 + + ! A temporary is needed for the result of either the transpose or matmul. + subroutine test4 (n, a, b) + integer :: n + real, dimension (n, n) :: a, b + a = matmul (transpose (a), b) ! { dg-warning "Creating array temporary" } + end subroutine test4 + + ! The temporary is needed here since the second argument to imp1 + ! has unknown intent. + subroutine test5 (n, a) + integer :: n + real, dimension (n, n) :: a + call imp1 (transpose (a), a) ! { dg-warning "Creating array temporary" } + end subroutine test5 + + ! No temporaries are needed here; imp1 can't modify either argument. + ! We have to pack the arguments, however. + subroutine test6 (n, a, b) + integer :: n + real, dimension (n, n) :: a, b + call imp1 (transpose (a), transpose (b)) ! { dg-warning "Creating array temporary" } + end subroutine test6 + + ! No temporaries are needed here; imp1 can't modify either argument. + ! We don't have to pack the arguments. + subroutine test6_bis (n, a, b) + integer :: n + real, dimension (n, n) :: a, b + call ext3 (transpose (a), transpose (b)) + end subroutine test6_bis + + ! No temporary is neede here; the second argument is intent(in). + subroutine test7 (n, a) + integer :: n + real, dimension (n, n) :: a + call ext1 (transpose (a), a) + end subroutine test7 + + ! The temporary is needed here though. + subroutine test8 (n, a) + integer :: n + real, dimension (n, n) :: a + call ext2 (transpose (a), a) ! { dg-warning "Creating array temporary" } + end subroutine test8 + + ! Silly, but we don't need any temporaries here. + subroutine test9 (n, a) + integer :: n + real, dimension (n, n) :: a + call ext1 (transpose (transpose (a)), a) + end subroutine test9 + + ! The outer transpose needs a temporary; the inner one doesn't. + subroutine test10 (n, a) + integer :: n + real, dimension (n, n) :: a + call ext2 (transpose (transpose (a)), a) ! { dg-warning "Creating array temporary" } + end subroutine test10 +end module foo + +! { dg-final { scan-tree-dump-times "struct\[^\\n\]*atmp" 4 "original" } } +! { dg-final { cleanup-tree-dump "original" } } diff --git a/gcc/testsuite/gfortran.dg/vect/pr45714-a.f b/gcc/testsuite/gfortran.dg/vect/pr45714-a.f new file mode 100644 index 00000000000..dd99d1fe56a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vect/pr45714-a.f @@ -0,0 +1,27 @@ +! { dg-do compile { target x86_64-*-* } } +! { dg-options "-O3 -march=core2 -mavx -ffast-math -mveclibabi=svml" } + + integer index(18),i,j,k,l,ipiv(18),info,ichange,neq,lda,ldb, + & nrhs,iplas + real*8 ep0(6),al10(18),al20(18),dg0(18),ep(6),al1(18), + & al2(18),dg(18),ddg(18),xm(6,18),h(18,18),ck(18),cn(18), + & c(18),d(18),phi(18),delta(18),r0(18),q(18),b(18),cphi(18), + & q1(18),q2(18),stri(6),htri(18),sg(18),r(42),xmc(6,18),aux(18), + & t(42),gl(18,18),gr(18,18),ee(6),c1111,c1122,c1212,dd, + & skl(3,3),xmtran(3,3),ddsdde(6,6),xx(6,18) + do + do i=1,18 + htri(i)=dabs(sg(i))-r0(i)-ck(i)*(dg(i)/dtime)**(1.d0/cn(i)) + do j=1,18 + enddo + enddo + do + if(i.ne.j) then + gr(index(i),1)=htri(i) + endif + call dgesv(neq,nrhs,gl,lda,ipiv,gr,ldb,info) + enddo + enddo + end + +! { dg-final { cleanup-tree-dump "vect" } } diff --git a/gcc/testsuite/gfortran.dg/vect/pr45714-b.f b/gcc/testsuite/gfortran.dg/vect/pr45714-b.f new file mode 100644 index 00000000000..a536e1f598f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vect/pr45714-b.f @@ -0,0 +1,27 @@ +! { dg-do compile { target powerpc*-*-* } } +! { dg-options "-O3 -mcpu=power7 -ffast-math -mveclibabi=mass" } + + integer index(18),i,j,k,l,ipiv(18),info,ichange,neq,lda,ldb, + & nrhs,iplas + real*8 ep0(6),al10(18),al20(18),dg0(18),ep(6),al1(18), + & al2(18),dg(18),ddg(18),xm(6,18),h(18,18),ck(18),cn(18), + & c(18),d(18),phi(18),delta(18),r0(18),q(18),b(18),cphi(18), + & q1(18),q2(18),stri(6),htri(18),sg(18),r(42),xmc(6,18),aux(18), + & t(42),gl(18,18),gr(18,18),ee(6),c1111,c1122,c1212,dd, + & skl(3,3),xmtran(3,3),ddsdde(6,6),xx(6,18) + do + do i=1,18 + htri(i)=dabs(sg(i))-r0(i)-ck(i)*(dg(i)/dtime)**(1.d0/cn(i)) + do j=1,18 + enddo + enddo + do + if(i.ne.j) then + gr(index(i),1)=htri(i) + endif + call dgesv(neq,nrhs,gl,lda,ipiv,gr,ldb,info) + enddo + enddo + end + +! { dg-final { cleanup-tree-dump "vect" } } diff --git a/gcc/testsuite/gfortran.dg/vector_subscript_bound_1.f90 b/gcc/testsuite/gfortran.dg/vector_subscript_bound_1.f90 new file mode 100644 index 00000000000..f4328504f24 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vector_subscript_bound_1.f90 @@ -0,0 +1,19 @@ +! { dg-do compile } +! +! PR fortran/45745 +! ICE with {L,U}BOUND intrinsic function as vector subscript on derived +! type component. +! +! Original test by Joost Van de Vondele <Joost.VandeVondele@pci.uzh.ch> + +MODULE pw_types + TYPE pw_type + REAL, DIMENSION ( : ), POINTER :: cr + END TYPE pw_type +CONTAINS + SUBROUTINE pw_write(pw) + TYPE(pw_type), INTENT(in) :: pw + PRINT *, pw%cr(LBOUND(pw%cr)) + PRINT *, pw%cr(UBOUND(pw%cr)) + END SUBROUTINE pw_write +END MODULE diff --git a/gcc/testsuite/gfortran.fortran-torture/compile/pr45738.f90 b/gcc/testsuite/gfortran.fortran-torture/compile/pr45738.f90 new file mode 100644 index 00000000000..b0541e35772 --- /dev/null +++ b/gcc/testsuite/gfortran.fortran-torture/compile/pr45738.f90 @@ -0,0 +1,11 @@ +PROGRAM TestInfinite + integer(8) :: bit_pattern_NegInf_i8 = -4503599627370496_8 + + integer(8) :: i + real(8) :: r + + r = transfer(bit_pattern_NegInf_i8_p,r) + i = transfer(r,i) + +END PROGRAM TestInfinite + diff --git a/gcc/testsuite/gnat.dg/const1.adb b/gcc/testsuite/gnat.dg/constant1.adb index 486e9632bc5..6cd1bcfd24e 100644 --- a/gcc/testsuite/gnat.dg/const1.adb +++ b/gcc/testsuite/gnat.dg/constant1.adb @@ -1,8 +1,8 @@ -- { dg-do compile } -procedure const1 is +procedure Constant1 is Def_Const : constant Integer; pragma Import (Ada, Def_Const); begin null; -end const1; +end; diff --git a/gcc/testsuite/gnat.dg/constant2.adb b/gcc/testsuite/gnat.dg/constant2.adb new file mode 100644 index 00000000000..41c7e914036 --- /dev/null +++ b/gcc/testsuite/gnat.dg/constant2.adb @@ -0,0 +1,11 @@ +-- { dg-do run } +-- { dg-options "-gnatVa" } + +with Constant2_Pkg1; use Constant2_Pkg1; + +procedure Constant2 is +begin + if Val then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/constant2_pkg1.ads b/gcc/testsuite/gnat.dg/constant2_pkg1.ads new file mode 100644 index 00000000000..8905d306432 --- /dev/null +++ b/gcc/testsuite/gnat.dg/constant2_pkg1.ads @@ -0,0 +1,7 @@ +with Constant2_Pkg2; use Constant2_Pkg2; + +package Constant2_Pkg1 is + + Val : constant Boolean := F1 and then F2; + +end Constant2_Pkg1; diff --git a/gcc/testsuite/gnat.dg/constant2_pkg2.adb b/gcc/testsuite/gnat.dg/constant2_pkg2.adb new file mode 100644 index 00000000000..e9ccadea2c9 --- /dev/null +++ b/gcc/testsuite/gnat.dg/constant2_pkg2.adb @@ -0,0 +1,13 @@ +package body Constant2_Pkg2 is + + function F1 return Boolean is + begin + return False; + end; + + function F2 return Boolean is + begin + return False; + end; + +end Constant2_Pkg2; diff --git a/gcc/testsuite/gnat.dg/constant2_pkg2.ads b/gcc/testsuite/gnat.dg/constant2_pkg2.ads new file mode 100644 index 00000000000..60b283c87b9 --- /dev/null +++ b/gcc/testsuite/gnat.dg/constant2_pkg2.ads @@ -0,0 +1,6 @@ +package Constant2_Pkg2 is + + function F1 return Boolean; + function F2 return Boolean; + +end Constant2_Pkg2; diff --git a/gcc/testsuite/gnat.dg/return2.adb b/gcc/testsuite/gnat.dg/return2.adb new file mode 100644 index 00000000000..65b7bf045ac --- /dev/null +++ b/gcc/testsuite/gnat.dg/return2.adb @@ -0,0 +1,33 @@ +-- { dg-do compile } +-- { dg-options "-O" } + +with Return2_Pkg; use Return2_Pkg; + +package body Return2 is + + function Value_Internal (Image : String) return Result_Internal_T is + begin + return (Member => False); + end; + + type Result_T is array (1 .. 2) of Result_Internal_T; + + function Value (Img : String) return T is + My_F : constant String := F; + Result : Result_T; + Value : T; + begin + for I in Result'Range loop + if G (My_F, I) /= "" then + Result (I) := Value_Internal (G (My_F, I)); + if Result (I).Member then + Value (Result (I).Data) := True; + else + raise Program_Error; + end if; + end if; + end loop; + return Value; + end; + +end Return2; diff --git a/gcc/testsuite/gnat.dg/return2.ads b/gcc/testsuite/gnat.dg/return2.ads new file mode 100644 index 00000000000..3e29910d2c7 --- /dev/null +++ b/gcc/testsuite/gnat.dg/return2.ads @@ -0,0 +1,18 @@ +package Return2 is + + type Kind_T is (One, Two); + + type T is array (Kind_T) of Boolean; + + type Result_Internal_T (Member : Boolean := False) is record + case Member is + when True => + Data : Kind_T := Kind_T'First; + when False => + null; + end case; + end record; + + function Value (Img : String) return T; + +end Return2; diff --git a/gcc/testsuite/gnat.dg/return2_pkg.ads b/gcc/testsuite/gnat.dg/return2_pkg.ads new file mode 100644 index 00000000000..f5738654a6d --- /dev/null +++ b/gcc/testsuite/gnat.dg/return2_pkg.ads @@ -0,0 +1,7 @@ +package Return2_Pkg is + + function F return String; + + function G (Line : String; Index : Positive) return String; + +end Return2_Pkg; diff --git a/gcc/testsuite/gnat.dg/specs/constant1.ads b/gcc/testsuite/gnat.dg/specs/constant1.ads new file mode 100644 index 00000000000..1c00c33f792 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/constant1.ads @@ -0,0 +1,22 @@ +-- { dg-do compile } + +with Constant1_Pkg; + +package Constant1 is + + type Timer_Id_T is new Constant1_Pkg.Timer_Id_T with null record; + + type Timer_Op_T (Pending : Boolean := False) is + record + case Pending is + when True => + Timer_Id : Timer_Id_T; + when False => + null; + end case; + end record; + + Timer : Timer_Op_T + := (True, Timer_Id_T'(Constant1_Pkg.Null_Timer_Id with null record)); + +end Constant1; diff --git a/gcc/testsuite/gnat.dg/specs/constant1_pkg.ads b/gcc/testsuite/gnat.dg/specs/constant1_pkg.ads new file mode 100644 index 00000000000..13300b1adaf --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/constant1_pkg.ads @@ -0,0 +1,11 @@ +package Constant1_Pkg is + + type Id_T is mod Natural'Last + 1; + + type Timer_Id_T is tagged record + Id : Id_T := Id_T'Last; + end record; + + Null_Timer_Id : constant Timer_Id_T := (Id => Id_T'Last - 1); + +end Constant1_Pkg; diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index 53db283db33..e52a23fe0d4 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -461,8 +461,21 @@ proc cleanup-ipa-dump { suffix } { } # Remove a stack usage file for the current test. -proc cleanup-stack-usage { args } { - cleanup-dump "su" +proc cleanup-stack-usage { } { + # This assumes that we are two frames down from dg-test or some other proc + # that stores the filename of the testcase in a local variable "name". + # A cleaner solution would require a new DejaGnu release. + upvar 2 name testcase + # The name might include a list of options; extract the file name. + set testcase [lindex $testcase 0] + remove-build-file "[file rootname [file tail $testcase]].su" + + # Clean up files for additional source files. + if [info exists additional_sources] { + foreach srcfile $additional_sources { + remove-build-file "[file rootname [file tail $srcfile]].su" + } + } } # Remove all dump files with the provided suffix. diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index cf8f8a71642..71ea4154385 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -339,7 +339,7 @@ proc dg-function-on-line { args } { } } - set pattern [format {%s:[^\t]*(\t.(frame|mask|file)[^\t]*)*\t[^:]+:%d\n} \ + set pattern [format {%s:[^\t]*(\t.(fnstart|frame|mask|file)[^\t]*)*\t[^:]+:%d\n} \ $symbol $line] # The lack of spaces around $pattern is important, since they'd diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 864f14e049d..cf78c95a5df 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -2425,7 +2425,9 @@ proc check_effective_target_vect_perm { } { } else { set et_vect_perm_saved 0 if { [istarget powerpc*-*-*] - || [istarget spu-*-*] } { + || [istarget spu-*-*] + || [istarget i?86-*-*] + || [istarget x86_64-*-*] } { set et_vect_perm_saved 1 } } @@ -2433,6 +2435,48 @@ proc check_effective_target_vect_perm { } { return $et_vect_perm_saved } +# Return 1 if the target plus current options supports vector permutation +# on byte-sized elements, 0 otherwise. +# +# This won't change for different subtargets so cache the result. + +proc check_effective_target_vect_perm_byte { } { + global et_vect_perm_byte + + if [info exists et_vect_perm_byte_saved] { + verbose "check_effective_target_vect_perm_byte: using cached result" 2 + } else { + set et_vect_perm_byte_saved 0 + if { [istarget powerpc*-*-*] + || [istarget spu-*-*] } { + set et_vect_perm_byte_saved 1 + } + } + verbose "check_effective_target_vect_perm_byte: returning $et_vect_perm_byte_saved" 2 + return $et_vect_perm_byte_saved +} + +# Return 1 if the target plus current options supports vector permutation +# on short-sized elements, 0 otherwise. +# +# This won't change for different subtargets so cache the result. + +proc check_effective_target_vect_perm_short { } { + global et_vect_perm_short + + if [info exists et_vect_perm_short_saved] { + verbose "check_effective_target_vect_perm_short: using cached result" 2 + } else { + set et_vect_perm_short_saved 0 + if { [istarget powerpc*-*-*] + || [istarget spu-*-*] } { + set et_vect_perm_short_saved 1 + } + } + verbose "check_effective_target_vect_perm_short: returning $et_vect_perm_short_saved" 2 + return $et_vect_perm_short_saved +} + # Return 1 if the target plus current options supports a vector # widening summation of *short* args into *int* result, 0 otherwise. # diff --git a/gcc/testsuite/obj-c++.dg/naming-1.mm b/gcc/testsuite/obj-c++.dg/naming-1.mm new file mode 100644 index 00000000000..aed2fd517af --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/naming-1.mm @@ -0,0 +1,26 @@ +/* Testing for detecting duplicate ivars. */ +/* { dg-do compile } */ + +typedef struct S { int i; } NSDictionary; + +@interface A +{ + NSDictionary * _userInfo; +} +@end + +@interface B : A +{ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ +} +@end + +@interface C : A +@end + +@interface D : C +{ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ +} +@end + diff --git a/gcc/testsuite/obj-c++.dg/naming-2.mm b/gcc/testsuite/obj-c++.dg/naming-2.mm new file mode 100644 index 00000000000..4b7860e10dd --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/naming-2.mm @@ -0,0 +1,40 @@ +/* Testing for detecting duplicate ivars. */ +/* { dg-do compile } */ + +typedef struct S { int i; } NSDictionary; + +@interface A +{ + NSDictionary * _userInfo; + int i1; + int i2; + int i3; + int i4; + int i5; + int i6; + int i7; +} +@end + +@interface B : A +{ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ + int ii1; + int ii2; + int ii3; + int ii4; + int ii5; + int ii6; + int ii7; +} +@end + +@interface C : A +@end + +@interface D : C +{ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ +} +@end + diff --git a/gcc/testsuite/obj-c++.dg/sync-2.mm b/gcc/testsuite/obj-c++.dg/sync-2.mm new file mode 100644 index 00000000000..c2143a4e95b --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/sync-2.mm @@ -0,0 +1,35 @@ +/* Make sure that @synchronized parses and a very basic test runs. */ +/* { dg-options "-fobjc-exceptions -fgnu-runtime" } */ + +#include "../objc-obj-c++-shared/Object1.h" + +int main (void) +{ + Object *a = [Object new]; + Object *b = [Object new]; + Object *c = [Object new]; + + /* This single-threaded test just checks that @synchronized() uses a + recursive mutex, and that the runtime at least doesn't crash + immediately upon finding it. + */ + @synchronized (a) + { + @synchronized (a) + { + @synchronized (b) + { + @synchronized (b) + { + @synchronized (c) + { + @synchronized (c) + { + return 0; + } + } + } + } + } + } +} diff --git a/gcc/testsuite/obj-c++.dg/too-many-args.mm b/gcc/testsuite/obj-c++.dg/too-many-args.mm new file mode 100644 index 00000000000..6fee1b31bd5 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/too-many-args.mm @@ -0,0 +1,10 @@ +/* { dg-do compile } */ + +@interface SomeClass ++ method:(int)foo; +@end + +int main(void) { + [SomeClass method:3, 4]; /* { dg-error "too many arguments to method \\'method:\\'" } */ + return 0; +} diff --git a/gcc/testsuite/objc.dg/invalid-method-1.m b/gcc/testsuite/objc.dg/invalid-method-1.m new file mode 100644 index 00000000000..78eae2c5815 --- /dev/null +++ b/gcc/testsuite/objc.dg/invalid-method-1.m @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* Test that we keep compiling if a method definition is found outside + of an @implementation context. +*/ + ++ (void)C { } /* { dg-error "method definition not in @implementation context" } */ + +/* We have another error here to test that the compiler is still going and + finding errors in the rest of the code. +*/ +@compatibility_alias class1 class2; /* { dg-warning "annot find class" } */ diff --git a/gcc/testsuite/objc.dg/naming-4.m b/gcc/testsuite/objc.dg/naming-4.m new file mode 100644 index 00000000000..9a85229f6a7 --- /dev/null +++ b/gcc/testsuite/objc.dg/naming-4.m @@ -0,0 +1,27 @@ +/* Testing for detecting duplicate ivars. */ +/* { dg-do compile } */ + +typedef struct S { int i; } NSDictionary; + +@interface A +{ + NSDictionary * _userInfo; +} +@end + +@interface B : A +{ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ +} +@end + +@interface C : A +@end + +@interface D : C +{ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ +} +@end diff --git a/gcc/testsuite/objc.dg/naming-5.m b/gcc/testsuite/objc.dg/naming-5.m new file mode 100644 index 00000000000..2e2786c41de --- /dev/null +++ b/gcc/testsuite/objc.dg/naming-5.m @@ -0,0 +1,42 @@ +/* Testing for detecting duplicate ivars. */ +/* { dg-do compile } */ + +typedef struct S { int i; } NSDictionary; + +@interface A +{ + NSDictionary * _userInfo; + int i1; + int i2; + int i3; + int i4; + int i5; + int i6; + int i7; +} +@end + +@interface B : A +{ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ + int ii1; + int ii2; + int ii3; + int ii4; + int ii5; + int ii6; + int ii7; + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ +} +@end + +@interface C : A +@end + +@interface D : C +{ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ + NSDictionary * _userInfo; /* { dg-error "duplicate member" } */ +} +@end + diff --git a/gcc/testsuite/objc.dg/sync-2.m b/gcc/testsuite/objc.dg/sync-2.m new file mode 100644 index 00000000000..c2143a4e95b --- /dev/null +++ b/gcc/testsuite/objc.dg/sync-2.m @@ -0,0 +1,35 @@ +/* Make sure that @synchronized parses and a very basic test runs. */ +/* { dg-options "-fobjc-exceptions -fgnu-runtime" } */ + +#include "../objc-obj-c++-shared/Object1.h" + +int main (void) +{ + Object *a = [Object new]; + Object *b = [Object new]; + Object *c = [Object new]; + + /* This single-threaded test just checks that @synchronized() uses a + recursive mutex, and that the runtime at least doesn't crash + immediately upon finding it. + */ + @synchronized (a) + { + @synchronized (a) + { + @synchronized (b) + { + @synchronized (b) + { + @synchronized (c) + { + @synchronized (c) + { + return 0; + } + } + } + } + } + } +} diff --git a/gcc/testsuite/objc.dg/too-many-args.m b/gcc/testsuite/objc.dg/too-many-args.m new file mode 100644 index 00000000000..6fee1b31bd5 --- /dev/null +++ b/gcc/testsuite/objc.dg/too-many-args.m @@ -0,0 +1,10 @@ +/* { dg-do compile } */ + +@interface SomeClass ++ method:(int)foo; +@end + +int main(void) { + [SomeClass method:3, 4]; /* { dg-error "too many arguments to method \\'method:\\'" } */ + return 0; +} diff --git a/gcc/testsuite/objc/execute/exceptions/throw-nil.m b/gcc/testsuite/objc/execute/exceptions/throw-nil.m index 3092d145170..cd9a797f5fd 100644 --- a/gcc/testsuite/objc/execute/exceptions/throw-nil.m +++ b/gcc/testsuite/objc/execute/exceptions/throw-nil.m @@ -1,8 +1,18 @@ #include <objc/objc.h> #include <objc/Object.h> +#ifdef __NEXT_RUNTIME__ +/* This test only runs for the GNU runtime. */ + +int main(void) +{ + return 0; +} + +#else + /* Test throwing a nil exception. A 'nil' exception can only be - * caugth by a generic exception handler. + caugth by a generic exception handler. */ int main (void) @@ -36,3 +46,5 @@ int main (void) return 0; } + +#endif diff --git a/gcc/toplev.c b/gcc/toplev.c index 900a0177519..5464d902b00 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -303,23 +303,6 @@ int flag_dump_rtl_in_asm = 0; the support provided depends on the backend. */ rtx stack_limit_rtx; -/* Positive if we should track variables, negative if we should run - the var-tracking pass only to discard debug annotations, zero if - we're not to run it. When flag_var_tracking == AUTODETECT_VALUE it - will be set according to optimize, debug_info_level and debug_hooks - in process_options (). */ -int flag_var_tracking = AUTODETECT_VALUE; - -/* Positive if we should track variables at assignments, negative if - we should run the var-tracking pass only to discard debug - annotations. When flag_var_tracking_assignments == - AUTODETECT_VALUE it will be set according to flag_var_tracking. */ -int flag_var_tracking_assignments = AUTODETECT_VALUE; - -/* Nonzero if we should toggle flag_var_tracking_assignments after - processing options and computing its default. */ -int flag_var_tracking_assignments_toggle = 0; - /* Type of stack check. */ enum stack_check_type flag_stack_check = NO_STACK_CHECK; diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index be8a84fef65..cf67fb8613e 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -2258,7 +2258,8 @@ is_ctrl_altering_stmt (gimple t) /* A non-pure/const call alters flow control if the current function has nonlocal labels. */ - if (!(flags & (ECF_CONST | ECF_PURE)) && cfun->has_nonlocal_label) + if (!(flags & (ECF_CONST | ECF_PURE | ECF_LEAF)) + && cfun->has_nonlocal_label) return true; /* A call also alters control flow if it does not return. */ @@ -2314,7 +2315,8 @@ stmt_can_make_abnormal_goto (gimple t) if (computed_goto_p (t)) return true; if (is_gimple_call (t)) - return gimple_has_side_effects (t) && cfun->has_nonlocal_label; + return (gimple_has_side_effects (t) && cfun->has_nonlocal_label + && !(gimple_call_flags (t) & ECF_LEAF)); return false; } diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index e1d2dfcadca..06b36e9d4fe 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -4709,6 +4709,76 @@ debug_rdg (struct graph *rdg) dump_rdg (stderr, rdg); } +static void +dot_rdg_1 (FILE *file, struct graph *rdg) +{ + int i; + + fprintf (file, "digraph RDG {\n"); + + for (i = 0; i < rdg->n_vertices; i++) + { + struct vertex *v = &(rdg->vertices[i]); + struct graph_edge *e; + + /* Highlight reads from memory. */ + if (RDG_MEM_READS_STMT (rdg, i)) + fprintf (file, "%d [style=filled, fillcolor=green]\n", i); + + /* Highlight stores to memory. */ + if (RDG_MEM_WRITE_STMT (rdg, i)) + fprintf (file, "%d [style=filled, fillcolor=red]\n", i); + + if (v->succ) + for (e = v->succ; e; e = e->succ_next) + switch (RDGE_TYPE (e)) + { + case input_dd: + fprintf (file, "%d -> %d [label=input] \n", i, e->dest); + break; + + case output_dd: + fprintf (file, "%d -> %d [label=output] \n", i, e->dest); + break; + + case flow_dd: + /* These are the most common dependences: don't print these. */ + fprintf (file, "%d -> %d \n", i, e->dest); + break; + + case anti_dd: + fprintf (file, "%d -> %d [label=anti] \n", i, e->dest); + break; + + default: + gcc_unreachable (); + } + } + + fprintf (file, "}\n\n"); +} + +/* Display the Reduced Dependence Graph using dotty. */ +extern void dot_rdg (struct graph *); + +DEBUG_FUNCTION void +dot_rdg (struct graph *rdg) +{ + /* When debugging, enable the following code. This cannot be used + in production compilers because it calls "system". */ +#if 0 + FILE *file = fopen ("/tmp/rdg.dot", "w"); + gcc_assert (file != NULL); + + dot_rdg_1 (file, rdg); + fclose (file); + + system ("dotty /tmp/rdg.dot &"); +#else + dot_rdg_1 (stderr, rdg); +#endif +} + /* This structure is used for recording the mapping statement index in the RDG. */ diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index da23516fd2b..85ad5342df3 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -559,7 +559,7 @@ extern void delete_tree_ssa (void); extern bool ssa_undefined_value_p (tree); extern void warn_uninit (tree, const char *, void *); extern unsigned int warn_uninitialized_vars (bool); -extern void execute_update_addresses_taken (bool); +extern void execute_update_addresses_taken (void); /* Call-back function for walk_use_def_chains(). At each reaching definition, a function with this prototype is called. */ diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 2d3958f2c04..b0627be0d3d 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1558,7 +1558,8 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, tree new_rhs; new_rhs = force_gimple_operand_gsi (&seq_gsi, gimple_assign_rhs1 (stmt), - true, NULL, false, GSI_NEW_STMT); + true, NULL, false, + GSI_CONTINUE_LINKING); gimple_assign_set_rhs1 (stmt, new_rhs); id->regimplify = false; } @@ -1977,12 +1978,13 @@ copy_phis_for_bb (basic_block bb, copy_body_data *id) edge_iterator ei; gimple phi; gimple_stmt_iterator si; + edge new_edge; + bool inserted = false; for (si = gsi_start (phi_nodes (bb)); !gsi_end_p (si); gsi_next (&si)) { tree res, new_res; gimple new_phi; - edge new_edge; phi = gsi_stmt (si); res = PHI_RESULT (phi); @@ -2022,13 +2024,19 @@ copy_phis_for_bb (basic_block bb, copy_body_data *id) { gimple_seq stmts = NULL; new_arg = force_gimple_operand (new_arg, &stmts, true, NULL); - gsi_insert_seq_on_edge_immediate (new_edge, stmts); + gsi_insert_seq_on_edge (new_edge, stmts); + inserted = true; } add_phi_arg (new_phi, new_arg, new_edge, gimple_phi_arg_location_from_edge (phi, old_edge)); } } } + + /* Commit the delayed edge insertions. */ + if (inserted) + FOR_EACH_EDGE (new_edge, ei, new_bb->preds) + gsi_commit_one_edge_insert (new_edge, NULL); } @@ -4155,6 +4163,7 @@ optimize_inline_calls (tree fn) basic_block bb; int last = n_basic_blocks; struct gimplify_ctx gctx; + bool inlined_p = false; /* There is no point in performing inlining if errors have already occurred -- and we might crash if we try to inline invalid @@ -4194,7 +4203,7 @@ optimize_inline_calls (tree fn) follow it; we'll trudge through them, processing their CALL_EXPRs along the way. */ FOR_EACH_BB (bb) - gimple_expand_calls_inline (bb, &id); + inlined_p |= gimple_expand_calls_inline (bb, &id); pop_gimplify_context (NULL); @@ -4210,18 +4219,19 @@ optimize_inline_calls (tree fn) } #endif - /* Fold the statements before compacting/renumbering the basic blocks. */ + /* Fold queued statements. */ fold_marked_statements (last, id.statements_to_fold); pointer_set_destroy (id.statements_to_fold); gcc_assert (!id.debug_stmts); - /* Renumber the (code) basic_blocks consecutively. */ - compact_blocks (); + /* If we didn't inline into the function there is nothing to do. */ + if (!inlined_p) + return 0; + /* Renumber the lexical scoping (non-code) blocks consecutively. */ number_blocks (fn); - fold_cond_expr_cond (); delete_unreachable_blocks_update_callgraph (&id); #ifdef ENABLE_CHECKING verify_cgraph_node (id.dst_node); @@ -4234,6 +4244,7 @@ optimize_inline_calls (tree fn) return (TODO_update_ssa | TODO_cleanup_cfg | (gimple_in_ssa_p (cfun) ? TODO_remove_unused_locals : 0) + | (gimple_in_ssa_p (cfun) ? TODO_update_address_taken : 0) | (profile_status != PROFILE_ABSENT ? TODO_rebuild_frequencies : 0)); } @@ -5111,9 +5122,6 @@ tree_function_versioning (tree old_decl, tree new_decl, DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id); - /* Renumber the lexical scoping (non-code) blocks consecutively. */ - number_blocks (id.dst_fn); - declare_inline_vars (DECL_INITIAL (new_decl), vars); if (!VEC_empty (tree, DECL_STRUCT_FUNCTION (old_decl)->local_decls)) diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c index ce18d6f1feb..9b4973f3bb0 100644 --- a/gcc/tree-optimize.c +++ b/gcc/tree-optimize.c @@ -149,37 +149,6 @@ struct gimple_opt_pass pass_all_early_optimizations = } }; -/* Pass: cleanup the CFG just before expanding trees to RTL. - This is just a round of label cleanups and case node grouping - because after the tree optimizers have run such cleanups may - be necessary. */ - -static unsigned int -execute_cleanup_cfg_pre_ipa (void) -{ - cleanup_tree_cfg (); - return 0; -} - -struct gimple_opt_pass pass_cleanup_cfg = -{ - { - GIMPLE_PASS, - "cleanup_cfg", /* name */ - NULL, /* gate */ - execute_cleanup_cfg_pre_ipa, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - PROP_cfg, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_dump_func /* todo_flags_finish */ - } -}; - /* Pass: cleanup the CFG just before expanding trees to RTL. This is just a round of label cleanups and case node grouping @@ -189,7 +158,6 @@ struct gimple_opt_pass pass_cleanup_cfg = static unsigned int execute_cleanup_cfg_post_optimizing (void) { - fold_cond_expr_cond (); cleanup_tree_cfg (); cleanup_dead_labels (); group_case_labels (); @@ -260,7 +228,7 @@ execute_free_datastructures (void) return 0; } -/* Pass: fixup_cfg. IPA passes, compilation of earlier functions or inlining +/* IPA passes, compilation of earlier functions or inlining might have changed some properties, such as marked functions nothrow, pure, const or noreturn. Remove redundant edges and basic blocks, and create new ones if necessary. @@ -306,7 +274,6 @@ execute_fixup_cfg (void) if (gimple_in_ssa_p (cfun)) { todo |= TODO_update_ssa | TODO_cleanup_cfg; - mark_symbols_for_renaming (stmt); update_stmt (stmt); } } @@ -316,11 +283,11 @@ execute_fixup_cfg (void) todo |= TODO_cleanup_cfg; } - maybe_clean_eh_stmt (stmt); + if (maybe_clean_eh_stmt (stmt) + && gimple_purge_dead_eh_edges (bb)) + todo |= TODO_cleanup_cfg; } - if (gimple_purge_dead_eh_edges (bb)) - todo |= TODO_cleanup_cfg; FOR_EACH_EDGE (e, ei, bb->succs) e->count = (e->count * count_scale + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 0dd6dd19a63..a16301cde02 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -355,10 +355,8 @@ extern struct gimple_opt_pass pass_lower_resx; extern struct gimple_opt_pass pass_build_cfg; extern struct gimple_opt_pass pass_tree_profile; extern struct gimple_opt_pass pass_early_tree_profile; -extern struct gimple_opt_pass pass_cleanup_cfg; extern struct gimple_opt_pass pass_referenced_vars; extern struct gimple_opt_pass pass_cleanup_eh; -extern struct gimple_opt_pass pass_fixup_cfg; extern struct gimple_opt_pass pass_sra; extern struct gimple_opt_pass pass_sra_early; extern struct gimple_opt_pass pass_early_ipa_sra; diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 0127b82c568..4364713ca57 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -216,6 +216,9 @@ struct access cannot be called from within FOR_EACH_REFERENCED_VAR. */ unsigned grp_to_be_replaced : 1; + /* Should TREE_NO_WARNING of a replacement be set? */ + unsigned grp_no_warning : 1; + /* Is it possible that the group refers to data which might be (directly or otherwise) modified? */ unsigned grp_maybe_modified : 1; @@ -1714,7 +1717,10 @@ create_access_replacement (struct access *access, bool rename) } SET_DECL_DEBUG_EXPR (repl, debug_expr); DECL_DEBUG_EXPR_IS_FROM (repl) = 1; - TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base); + if (access->grp_no_warning) + TREE_NO_WARNING (repl) = 1; + else + TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base); } else TREE_NO_WARNING (repl) = 1; @@ -1970,12 +1976,17 @@ create_artificial_child_access (struct access *parent, struct access *model, tree expr = parent->base; gcc_assert (!model->grp_unscalarizable_region); - if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset, - model->type)) - return NULL; access = (struct access *) pool_alloc (access_pool); memset (access, 0, sizeof (struct access)); + if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset, + model->type)) + { + access->grp_no_warning = true; + expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base, + new_offset, model, NULL, false); + } + access->base = parent->base; access->expr = expr; access->offset = new_offset; @@ -2016,11 +2027,16 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc) { tree t = lacc->base; + lacc->type = racc->type; if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t), lacc->offset, racc->type)) + lacc->expr = t; + else { - lacc->expr = t; - lacc->type = racc->type; + lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base), + lacc->base, lacc->offset, + racc, NULL, false); + lacc->grp_no_warning = true; } return false; } diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 42b8a58b9d3..cf4321aa038 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -1342,9 +1342,7 @@ get_base_constructor (tree base, tree *offset) switch (TREE_CODE (base)) { case VAR_DECL: - if (!TREE_READONLY (base) - || ((TREE_STATIC (base) || DECL_EXTERNAL (base)) - && !varpool_get_node (base)->const_value_known)) + if (!const_value_known_p (base)) return NULL_TREE; /* Fallthru. */ diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index c1abb40c529..54a35af4a85 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -2178,6 +2178,48 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si) update_stmt_if_modified (stmt); eliminate_redundant_computations (&si); stmt = gsi_stmt (si); + + /* Perform simple redundant store elimination. */ + if (gimple_assign_single_p (stmt) + && TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME) + { + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_assign_rhs1 (stmt); + tree cached_lhs; + gimple new_stmt; + if (TREE_CODE (rhs) == SSA_NAME) + { + tree tem = SSA_NAME_VALUE (rhs); + if (tem) + rhs = tem; + } + /* Build a new statement with the RHS and LHS exchanged. */ + if (TREE_CODE (rhs) == SSA_NAME) + { + gimple defstmt = SSA_NAME_DEF_STMT (rhs); + new_stmt = gimple_build_assign (rhs, lhs); + SSA_NAME_DEF_STMT (rhs) = defstmt; + } + else + new_stmt = gimple_build_assign (rhs, lhs); + gimple_set_vuse (new_stmt, gimple_vuse (stmt)); + cached_lhs = lookup_avail_expr (new_stmt, false); + if (cached_lhs + && rhs == cached_lhs) + { + basic_block bb = gimple_bb (stmt); + int lp_nr = lookup_stmt_eh_lp (stmt); + unlink_stmt_vdef (stmt); + gsi_remove (&si, true); + if (lp_nr != 0) + { + bitmap_set_bit (need_eh_cleanup, bb->index); + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, " Flagged to clear EH edges.\n"); + } + return; + } + } } /* Record any additional equivalences created by this statement. */ diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index 2ced3070d48..187f53c7a66 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -162,10 +162,8 @@ constant_after_peeling (tree op, gimple stmt, struct loop *loop) /* First make fast look if we see constant array inside. */ while (handled_component_p (base)) base = TREE_OPERAND (base, 0); - if ((DECL_P (base) - && TREE_STATIC (base) - && TREE_READONLY (base) - && varpool_get_node (base)->const_value_known) + if ((DECL_P (base) == VAR_DECL + && const_value_known_p (base)) || CONSTANT_CLASS_P (base)) { /* If so, see if we understand all the indices. */ diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c index e08d2e7ae0c..c97960cfdf7 100644 --- a/gcc/tree-ssa-propagate.c +++ b/gcc/tree-ssa-propagate.c @@ -1122,12 +1122,12 @@ substitute_and_fold (ssa_prop_get_value_fn get_value_fn, { did_replace = true; prop_stats.num_stmts_folded++; + stmt = gsi_stmt (oldi); + update_stmt (stmt); } - /* Only replace real uses if we couldn't fold the - statement using value range information. */ - if (get_value_fn - && !did_replace) + /* Replace real uses in the statement. */ + if (get_value_fn) did_replace |= replace_uses_in (stmt, get_value_fn); /* If we made a replacement, fold the statement. */ diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 10c7ab91496..0b83b37e02f 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -1885,9 +1885,9 @@ non_rewritable_mem_ref_base (tree ref) return NULL_TREE; } -/* When possible, clear ADDRESSABLE bit or set the REGISTER bit - and mark the variable VAR for conversion into SSA. Returns true - when updating stmts is required. */ +/* When possible, clear TREE_ADDRESSABLE bit or set DECL_GIMPLE_REG_P bit and + mark the variable VAR for conversion into SSA. Return true when updating + stmts is required. */ static bool maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs) @@ -1918,11 +1918,12 @@ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs) update_vops = true; if (dump_file) { - fprintf (dump_file, "No longer having address taken "); + fprintf (dump_file, "No longer having address taken: "); print_generic_expr (dump_file, var, 0); fprintf (dump_file, "\n"); } } + if (!DECL_GIMPLE_REG_P (var) && !bitmap_bit_p (not_reg_needs, DECL_UID (var)) && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE @@ -1935,7 +1936,7 @@ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs) update_vops = true; if (dump_file) { - fprintf (dump_file, "Decl is now a gimple register "); + fprintf (dump_file, "Now a gimple register: "); print_generic_expr (dump_file, var, 0); fprintf (dump_file, "\n"); } @@ -1947,14 +1948,14 @@ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs) /* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables. */ void -execute_update_addresses_taken (bool do_optimize) +execute_update_addresses_taken (void) { - tree var; gimple_stmt_iterator gsi; basic_block bb; bitmap addresses_taken = BITMAP_ALLOC (NULL); bitmap not_reg_needs = BITMAP_ALLOC (NULL); bool update_vops = false; + tree var; unsigned i; /* Collect into ADDRESSES_TAKEN all variables whose address is taken within @@ -2047,20 +2048,16 @@ execute_update_addresses_taken (bool do_optimize) } } - /* When possible, clear ADDRESSABLE bit or set the REGISTER bit - and mark variable for conversion into SSA. */ - if (optimize && do_optimize) - { - /* We cannot iterate over all referenced vars as that can contain - unused vars from BLOCK trees which cause code generation - differences for -g vs. -g0. */ - for (var = DECL_ARGUMENTS (cfun->decl); var; var = DECL_CHAIN (var)) - update_vops |= maybe_optimize_var (var, addresses_taken, not_reg_needs); - FOR_EACH_VEC_ELT (tree, cfun->local_decls, i, var) - update_vops |= maybe_optimize_var (var, addresses_taken, not_reg_needs); - } + /* We cannot iterate over all referenced vars because that can contain + unused vars from BLOCK trees, which causes code generation differences + for -g vs. -g0. */ + for (var = DECL_ARGUMENTS (cfun->decl); var; var = DECL_CHAIN (var)) + update_vops |= maybe_optimize_var (var, addresses_taken, not_reg_needs); + + FOR_EACH_VEC_ELT (tree, cfun->local_decls, i, var) + update_vops |= maybe_optimize_var (var, addresses_taken, not_reg_needs); - /* Operand caches needs to be recomputed for operands referencing the updated + /* Operand caches need to be recomputed for operands referencing the updated variables. */ if (update_vops) { diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 0d63fe9fe63..c005aba4977 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -338,8 +338,8 @@ release_dead_ssa_names (void) int n = 0; referenced_var_iterator rvi; - /* Current defs point to various dead SSA names that in turn points to dead - statements so bunch of dead memory is held from releasing. */ + /* Current defs point to various dead SSA names that in turn point to + eventually dead variables so a bunch of memory is held live. */ FOR_EACH_REFERENCED_VAR (t, rvi) set_current_def (t, NULL); /* Now release the freelist. */ @@ -356,12 +356,10 @@ release_dead_ssa_names (void) } FREE_SSANAMES (cfun) = NULL; - /* Cgraph edges has been invalidated and point to dead statement. We need to - remove them now and will rebuild it before next IPA pass. */ - cgraph_node_remove_callees (cgraph_node (current_function_decl)); - + statistics_counter_event (cfun, "SSA names released", n); if (dump_file) - fprintf (dump_file, "Released %i names, %.2f%%\n", n, n * 100.0 / num_ssa_names); + fprintf (dump_file, "Released %i names, %.2f%%\n", + n, n * 100.0 / num_ssa_names); return 0; } diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index 0d1e3381738..71825137cd7 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -2287,7 +2287,9 @@ vect_analyze_data_ref_access (struct data_reference *dr) } /* Consecutive? */ - if (!tree_int_cst_compare (step, TYPE_SIZE_UNIT (scalar_type))) + if (!tree_int_cst_compare (step, TYPE_SIZE_UNIT (scalar_type)) + || (dr_step < 0 + && !compare_tree_int (TYPE_SIZE_UNIT (scalar_type), -dr_step))) { /* Mark that it is not interleaving. */ DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt)) = NULL; @@ -2970,6 +2972,7 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop, tree vptr; gimple_stmt_iterator incr_gsi; bool insert_after; + bool negative; tree indx_before_incr, indx_after_incr; gimple incr; tree step; @@ -3002,6 +3005,7 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop, *inv_p = true; else *inv_p = false; + negative = tree_int_cst_compare (step, size_zero_node) < 0; /* Create an expression for the first address accessed by this load in LOOP. */ @@ -3160,6 +3164,8 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop, LOOP is zero. In this case the step here is also zero. */ if (*inv_p) step = size_zero_node; + else if (negative) + step = fold_build1 (NEGATE_EXPR, TREE_TYPE (step), step); standard_iv_increment_position (loop, &incr_gsi, &insert_after); diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 3db0ec1b850..b120dc60961 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -3145,6 +3145,13 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, if (!STMT_VINFO_DATA_REF (stmt_info)) return false; + if (tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "negative step for store."); + return false; + } + if (STMT_VINFO_STRIDED_ACCESS (stmt_info)) { strided_store = true; @@ -3425,6 +3432,68 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, return true; } +/* Given a vector type VECTYPE returns a builtin DECL to be used + for vector permutation and stores a mask into *MASK that implements + reversal of the vector elements. If that is impossible to do + returns NULL (and *MASK is unchanged). */ + +static tree +perm_mask_for_reverse (tree vectype, tree *mask) +{ + tree builtin_decl; + tree mask_element_type, mask_type; + tree mask_vec = NULL; + int i; + int nunits; + if (!targetm.vectorize.builtin_vec_perm) + return NULL; + + builtin_decl = targetm.vectorize.builtin_vec_perm (vectype, + &mask_element_type); + if (!builtin_decl || !mask_element_type) + return NULL; + + mask_type = get_vectype_for_scalar_type (mask_element_type); + nunits = TYPE_VECTOR_SUBPARTS (vectype); + if (TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type)) + return NULL; + + for (i = 0; i < nunits; i++) + mask_vec = tree_cons (NULL, build_int_cst (mask_element_type, i), mask_vec); + mask_vec = build_vector (mask_type, mask_vec); + + if (!targetm.vectorize.builtin_vec_perm_ok (vectype, mask_vec)) + return NULL; + if (mask) + *mask = mask_vec; + return builtin_decl; +} + +/* Given a vector variable X, that was generated for the scalar LHS of + STMT, generate instructions to reverse the vector elements of X, + insert them a *GSI and return the permuted vector variable. */ + +static tree +reverse_vec_elements (tree x, gimple stmt, gimple_stmt_iterator *gsi) +{ + tree vectype = TREE_TYPE (x); + tree mask_vec, builtin_decl; + tree perm_dest, data_ref; + gimple perm_stmt; + + builtin_decl = perm_mask_for_reverse (vectype, &mask_vec); + + perm_dest = vect_create_destination_var (gimple_assign_lhs (stmt), vectype); + + /* Generate the permute statement. */ + perm_stmt = gimple_build_call (builtin_decl, 3, x, x, mask_vec); + data_ref = make_ssa_name (perm_dest, perm_stmt); + gimple_call_set_lhs (perm_stmt, data_ref); + vect_finish_stmt_generation (stmt, perm_stmt, gsi); + + return data_ref; +} + /* vectorizable_load. Check if STMT reads a non scalar data-ref (array/pointer/structure) that @@ -3467,6 +3536,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, gimple first_stmt; tree scalar_type; bool inv_p; + bool negative; bool compute_in_loop = false; struct loop *at_loop; int vec_num; @@ -3529,6 +3599,14 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, if (!STMT_VINFO_DATA_REF (stmt_info)) return false; + negative = tree_int_cst_compare (DR_STEP (dr), size_zero_node) < 0; + if (negative && ncopies > 1) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "multiple types with negative step."); + return false; + } + scalar_type = TREE_TYPE (DR_REF (dr)); mode = TYPE_MODE (vectype); @@ -3563,6 +3641,25 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, return false; } + if (negative) + { + gcc_assert (!strided_load); + alignment_support_scheme = vect_supportable_dr_alignment (dr, false); + if (alignment_support_scheme != dr_aligned + && alignment_support_scheme != dr_unaligned_supported) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "negative step but alignment required."); + return false; + } + if (!perm_mask_for_reverse (vectype, NULL)) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "negative step and reversing not supported."); + return false; + } + } + if (!vec_stmt) /* transformation not required. */ { STMT_VINFO_TYPE (stmt_info) = load_vec_info_type; @@ -3737,6 +3834,9 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, else at_loop = loop; + if (negative) + offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1); + prev_stmt_info = NULL; for (j = 0; j < ncopies; j++) { @@ -3925,6 +4025,12 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, gcc_unreachable (); /* FORNOW. */ } + if (negative) + { + new_temp = reverse_vec_elements (new_temp, stmt, gsi); + new_stmt = SSA_NAME_DEF_STMT (new_temp); + } + /* Collect vector loads and later create their permutation in vect_transform_strided_load (). */ if (strided_load || slp_perm) @@ -4410,7 +4516,7 @@ vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi, bool is_store = false; gimple vec_stmt = NULL; stmt_vec_info stmt_info = vinfo_for_stmt (stmt); - gimple orig_stmt_in_pattern; + gimple orig_stmt_in_pattern, orig_scalar_stmt = stmt; bool done; switch (STMT_VINFO_TYPE (stmt_info)) @@ -4478,6 +4584,7 @@ vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi, case call_vec_info_type: gcc_assert (!slp_node); done = vectorizable_call (stmt, gsi, &vec_stmt); + stmt = gsi_stmt (*gsi); break; case reduc_vec_info_type: @@ -4556,7 +4663,8 @@ vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi, documentation of vect_pattern_recog. */ if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo)) { - gcc_assert (STMT_VINFO_RELATED_STMT (stmt_vinfo) == stmt); + gcc_assert (STMT_VINFO_RELATED_STMT (stmt_vinfo) + == orig_scalar_stmt); STMT_VINFO_VEC_STMT (stmt_vinfo) = vec_stmt; } } diff --git a/gcc/tree.c b/gcc/tree.c index 7746628375d..738fa9cdbe8 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -6123,9 +6123,6 @@ type_hash_canon (unsigned int hashcode, tree type) being passed. */ gcc_assert (TYPE_MAIN_VARIANT (type) == type); - if (!lang_hooks.types.hash_types) - return type; - /* See if the type is in the hash table already. If so, return it. Otherwise, add the type. */ t1 = type_hash_lookup (hashcode, type); @@ -7093,21 +7090,20 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision, ret = itype; if (host_integerp (TYPE_MAX_VALUE (itype), 1)) ret = type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype); - if (precision <= MAX_INT_CACHED_PREC && lang_hooks.types.hash_types) + if (precision <= MAX_INT_CACHED_PREC) nonstandard_integer_type_cache[precision + unsignedp] = ret; return ret; } -/* Create a range of some discrete type TYPE (an INTEGER_TYPE, - ENUMERAL_TYPE or BOOLEAN_TYPE), with low bound LOWVAL and - high bound HIGHVAL. */ +/* Create a range of some discrete type TYPE (an INTEGER_TYPE, ENUMERAL_TYPE + or BOOLEAN_TYPE) with low bound LOWVAL and high bound HIGHVAL. If SHARED + is true, reuse such a type that has already been constructed. */ -tree -build_range_type (tree type, tree lowval, tree highval) +static tree +build_range_type_1 (tree type, tree lowval, tree highval, bool shared) { tree itype = make_node (INTEGER_TYPE); - hashval_t hash; TREE_TYPE (itype) = type; @@ -7131,10 +7127,32 @@ build_range_type (tree type, tree lowval, tree highval) SET_TYPE_STRUCTURAL_EQUALITY (itype); return itype; } - hash = iterative_hash_expr (TYPE_MIN_VALUE (itype), 0); - hash = iterative_hash_expr (TYPE_MAX_VALUE (itype), hash); - hash = iterative_hash_hashval_t (TYPE_HASH (type), hash); - return type_hash_canon (hash, itype); + + if (shared) + { + hashval_t hash = iterative_hash_expr (TYPE_MIN_VALUE (itype), 0); + hash = iterative_hash_expr (TYPE_MAX_VALUE (itype), hash); + hash = iterative_hash_hashval_t (TYPE_HASH (type), hash); + itype = type_hash_canon (hash, itype); + } + + return itype; +} + +/* Wrapper around build_range_type_1 with SHARED set to true. */ + +tree +build_range_type (tree type, tree lowval, tree highval) +{ + return build_range_type_1 (type, lowval, highval, true); +} + +/* Wrapper around build_range_type_1 with SHARED set to false. */ + +tree +build_nonshared_range_type (tree type, tree lowval, tree highval) +{ + return build_range_type_1 (type, lowval, highval, false); } /* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE. @@ -7205,13 +7223,12 @@ subrange_type_for_debug_p (const_tree type, tree *lowval, tree *highval) /* Construct, lay out and return the type of arrays of elements with ELT_TYPE and number of elements specified by the range of values of INDEX_TYPE. - If such a type has already been constructed, reuse it. */ + If SHARED is true, reuse such a type that has already been constructed. */ -tree -build_array_type (tree elt_type, tree index_type) +static tree +build_array_type_1 (tree elt_type, tree index_type, bool shared) { tree t; - hashval_t hashcode = 0; if (TREE_CODE (elt_type) == FUNCTION_TYPE) { @@ -7231,10 +7248,13 @@ build_array_type (tree elt_type, tree index_type) if (TYPE_STRUCTURAL_EQUALITY_P (t)) return t; - hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode); - if (index_type) - hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); - t = type_hash_canon (hashcode, t); + if (shared) + { + hashval_t hashcode = iterative_hash_object (TYPE_HASH (elt_type), 0); + if (index_type) + hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); + t = type_hash_canon (hashcode, t); + } if (TYPE_CANONICAL (t) == t) { @@ -7244,13 +7264,31 @@ build_array_type (tree elt_type, tree index_type) else if (TYPE_CANONICAL (elt_type) != elt_type || (index_type && TYPE_CANONICAL (index_type) != index_type)) TYPE_CANONICAL (t) - = build_array_type (TYPE_CANONICAL (elt_type), - index_type ? TYPE_CANONICAL (index_type) : NULL); + = build_array_type_1 (TYPE_CANONICAL (elt_type), + index_type + ? TYPE_CANONICAL (index_type) : NULL_TREE, + shared); } return t; } +/* Wrapper around build_array_type_1 with SHARED set to true. */ + +tree +build_array_type (tree elt_type, tree index_type) +{ + return build_array_type_1 (elt_type, index_type, true); +} + +/* Wrapper around build_array_type_1 with SHARED set to false. */ + +tree +build_nonshared_array_type (tree elt_type, tree index_type) +{ + return build_array_type_1 (elt_type, index_type, false); +} + /* Recursively examines the array elements of TYPE, until a non-array element type is found. */ @@ -9186,6 +9224,9 @@ local_define_builtin (const char *name, tree type, enum built_in_function code, TREE_NOTHROW (decl) = 1; if (ecf_flags & ECF_MALLOC) DECL_IS_MALLOC (decl) = 1; + if (ecf_flags & ECF_LEAF) + DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"), + NULL, DECL_ATTRIBUTES (decl)); built_in_decls[code] = decl; implicit_built_in_decls[code] = decl; @@ -9209,10 +9250,10 @@ build_common_builtin_nodes (void) if (built_in_decls[BUILT_IN_MEMCPY] == NULL) local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY, - "memcpy", ECF_NOTHROW); + "memcpy", ECF_NOTHROW | ECF_LEAF); if (built_in_decls[BUILT_IN_MEMMOVE] == NULL) local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE, - "memmove", ECF_NOTHROW); + "memmove", ECF_NOTHROW | ECF_LEAF); } if (built_in_decls[BUILT_IN_MEMCMP] == NULL) @@ -9221,7 +9262,7 @@ build_common_builtin_nodes (void) const_ptr_type_node, size_type_node, NULL_TREE); local_define_builtin ("__builtin_memcmp", ftype, BUILT_IN_MEMCMP, - "memcmp", ECF_PURE | ECF_NOTHROW); + "memcmp", ECF_PURE | ECF_NOTHROW | ECF_LEAF); } if (built_in_decls[BUILT_IN_MEMSET] == NULL) @@ -9230,7 +9271,7 @@ build_common_builtin_nodes (void) ptr_type_node, integer_type_node, size_type_node, NULL_TREE); local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET, - "memset", ECF_NOTHROW); + "memset", ECF_NOTHROW | ECF_LEAF); } if (built_in_decls[BUILT_IN_ALLOCA] == NULL) @@ -9238,7 +9279,7 @@ build_common_builtin_nodes (void) ftype = build_function_type_list (ptr_type_node, size_type_node, NULL_TREE); local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA, - "alloca", ECF_MALLOC | ECF_NOTHROW); + "alloca", ECF_MALLOC | ECF_NOTHROW | ECF_LEAF); } /* If we're checking the stack, `alloca' can throw. */ @@ -9250,7 +9291,7 @@ build_common_builtin_nodes (void) ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_init_trampoline", ftype, BUILT_IN_INIT_TRAMPOLINE, - "__builtin_init_trampoline", ECF_NOTHROW); + "__builtin_init_trampoline", ECF_NOTHROW | ECF_LEAF); ftype = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_adjust_trampoline", ftype, @@ -9284,12 +9325,12 @@ build_common_builtin_nodes (void) ftype = build_function_type_list (ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_stack_save", ftype, BUILT_IN_STACK_SAVE, - "__builtin_stack_save", ECF_NOTHROW); + "__builtin_stack_save", ECF_NOTHROW | ECF_LEAF); ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); local_define_builtin ("__builtin_stack_restore", ftype, BUILT_IN_STACK_RESTORE, - "__builtin_stack_restore", ECF_NOTHROW); + "__builtin_stack_restore", ECF_NOTHROW | ECF_LEAF); ftype = build_function_type_list (void_type_node, NULL_TREE); local_define_builtin ("__builtin_profile_func_enter", ftype, @@ -9304,7 +9345,7 @@ build_common_builtin_nodes (void) ftype = build_function_type_list (void_type_node, NULL_TREE); local_define_builtin ("__builtin_cxa_end_cleanup", ftype, BUILT_IN_CXA_END_CLEANUP, - "__cxa_end_cleanup", ECF_NORETURN); + "__cxa_end_cleanup", ECF_NORETURN | ECF_LEAF); } ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); @@ -9323,12 +9364,12 @@ build_common_builtin_nodes (void) ftype = build_function_type_list (ptr_type_node, integer_type_node, NULL_TREE); local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER, - "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW); + "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW | ECF_LEAF); tmp = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0); ftype = build_function_type_list (tmp, integer_type_node, NULL_TREE); local_define_builtin ("__builtin_eh_filter", ftype, BUILT_IN_EH_FILTER, - "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW); + "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW | ECF_LEAF); ftype = build_function_type_list (void_type_node, integer_type_node, integer_type_node, @@ -9370,11 +9411,11 @@ build_common_builtin_nodes (void) built_in_names[mcode] = concat ("__mul", mode_name_buf, "3", NULL); local_define_builtin (built_in_names[mcode], ftype, mcode, - built_in_names[mcode], ECF_CONST | ECF_NOTHROW); + built_in_names[mcode], ECF_CONST | ECF_NOTHROW | ECF_LEAF); built_in_names[dcode] = concat ("__div", mode_name_buf, "3", NULL); local_define_builtin (built_in_names[dcode], ftype, dcode, - built_in_names[dcode], ECF_CONST | ECF_NOTHROW); + built_in_names[dcode], ECF_CONST | ECF_NOTHROW | ECF_LEAF); } } } diff --git a/gcc/tree.h b/gcc/tree.h index 1ff9d35effa..03950d63059 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3002,31 +3002,6 @@ struct GTY(()) tree_parm_decl { multiple translation units should be merged. */ #define DECL_ONE_ONLY(NODE) (DECL_COMDAT_GROUP (NODE) != NULL_TREE) -/* A replaceable function is one which may be replaced at link-time - with an entirely different definition, provided that the - replacement has the same type. For example, functions declared - with __attribute__((weak)) on most systems are replaceable. - - COMDAT functions are not replaceable, since all definitions of the - function must be equivalent. It is important that COMDAT functions - not be treated as replaceable so that use of C++ template - instantiations is not penalized. - - In other respects, the condition is usually equivalent to whether - the function binds to the current module (shared library or executable). - However, weak functions can always be overridden by earlier TUs - in the same module, even if they bind locally to that module. - - For example, DECL_REPLACEABLE is used to determine whether or not a - function (including a template instantiation) which is not - explicitly declared "inline" can be inlined. If the function is - DECL_REPLACEABLE then it is not safe to do the inlining, since the - implementation chosen at link-time may be different. However, a - function that is not DECL_REPLACEABLE can be inlined, since all - versions of the function will be functionally identical. */ -#define DECL_REPLACEABLE_P(NODE) \ - (!DECL_COMDAT (NODE) && (DECL_WEAK (NODE) || !targetm.binds_local_p (NODE))) - /* The name of the object as the assembler will see it (but before any translations made by ASM_OUTPUT_LABELREF). Often this is the same as DECL_NAME. It is an IDENTIFIER_NODE. */ @@ -4102,6 +4077,7 @@ extern tree build_opaque_vector_type (tree innertype, int nunits); extern tree build_type_no_quals (tree); extern tree build_index_type (tree); extern tree build_array_type (tree, tree); +extern tree build_nonshared_array_type (tree, tree); extern tree build_function_type (tree, tree); extern tree build_function_type_list (tree, ...); extern tree build_function_type_skip_args (tree, bitmap); @@ -5127,6 +5103,7 @@ extern void build_common_tree_nodes_2 (int); extern void build_common_builtin_nodes (void); extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int); extern tree build_range_type (tree, tree, tree); +extern tree build_nonshared_range_type (tree, tree, tree); extern bool subrange_type_for_debug_p (const_tree, tree *, tree *); extern HOST_WIDE_INT int_cst_value (const_tree); extern HOST_WIDEST_INT widest_int_cst_value (const_tree); @@ -5222,6 +5199,8 @@ extern tree build_duplicate_type (tree); /* Function does not read or write memory (but may have side effects, so it does not necessarily fit ECF_CONST). */ #define ECF_NOVOPS (1 << 9) +/* The function does not lead to calls within current function unit. */ +#define ECF_LEAF (1 << 10) extern int flags_from_decl_or_type (const_tree); extern int call_expr_flags (const_tree); @@ -5295,6 +5274,8 @@ extern void process_pending_assemble_externals (void); extern void finish_aliases_1 (void); extern void finish_aliases_2 (void); extern void remove_unreachable_alias_pairs (void); +extern bool decl_replaceable_p (tree); +extern bool decl_binds_to_current_def_p (tree); /* In stmt.c */ extern void expand_computed_goto (tree); diff --git a/gcc/varasm.c b/gcc/varasm.c index 1c2a525c523..b02462bdec4 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6381,6 +6381,30 @@ default_use_anchors_for_symbol_p (const_rtx symbol) return true; } +/* Return true when RESOLUTION indicate that symbol will be bound to the + definition provided by current .o file. */ + +static bool +resolution_to_local_definition_p (enum ld_plugin_symbol_resolution resolution) +{ + return (resolution == LDPR_PREVAILING_DEF + || resolution == LDPR_PREVAILING_DEF_IRONLY); +} + +/* Return true when RESOLUTION indicate that symbol will be bound locally + within current executable or DSO. */ + +static bool +resolution_local_p (enum ld_plugin_symbol_resolution resolution) +{ + return (resolution == LDPR_PREVAILING_DEF + || resolution == LDPR_PREVAILING_DEF_IRONLY + || resolution == LDPR_PREEMPTED_REG + || resolution == LDPR_PREEMPTED_IR + || resolution == LDPR_RESOLVED_IR + || resolution == LDPR_RESOLVED_EXEC); +} + /* Assume ELF-ish defaults, since that's pretty much the most liberal wrt cross-module name binding. */ @@ -6394,12 +6418,41 @@ bool default_binds_local_p_1 (const_tree exp, int shlib) { bool local_p; + bool resolved_locally = false; + bool resolved_to_local_def = false; + + /* With resolution file in hands, take look into resolutions. + We can't just return true for resolved_localy symbols, + because dynamic linking might overwrite symbols + in shared libraries. */ + if (TREE_CODE (exp) == VAR_DECL && TREE_PUBLIC (exp) + && (TREE_STATIC (exp) || DECL_EXTERNAL (exp))) + { + struct varpool_node *vnode = varpool_get_node (exp); + if (vnode && resolution_local_p (vnode->resolution)) + resolved_locally = true; + if (vnode + && resolution_to_local_definition_p (vnode->resolution)) + resolved_to_local_def = true; + } + else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp)) + { + struct cgraph_node *node = cgraph_get_node_or_alias (exp); + if (node + && resolution_local_p (node->resolution)) + resolved_locally = true; + if (node + && resolution_to_local_definition_p (node->resolution)) + resolved_to_local_def = true; + } /* A non-decl is an entry in the constant pool. */ if (!DECL_P (exp)) local_p = true; /* Weakrefs may not bind locally, even though the weakref itself is - always static and therefore local. */ + always static and therefore local. + FIXME: We can resolve this more curefuly by looking at the weakref + alias. */ else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))) local_p = false; /* Static variables are always local. */ @@ -6407,11 +6460,12 @@ default_binds_local_p_1 (const_tree exp, int shlib) local_p = true; /* A variable is local if the user has said explicitly that it will be. */ - else if (DECL_VISIBILITY_SPECIFIED (exp) + else if ((DECL_VISIBILITY_SPECIFIED (exp) + || resolved_to_local_def) && DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT) local_p = true; /* Variables defined outside this object might not be local. */ - else if (DECL_EXTERNAL (exp)) + else if (DECL_EXTERNAL (exp) && !resolved_locally) local_p = false; /* If defined in this object and visibility is not default, must be local. */ @@ -6419,16 +6473,17 @@ default_binds_local_p_1 (const_tree exp, int shlib) local_p = true; /* Default visibility weak data can be overridden by a strong symbol in another module and so are not local. */ - else if (DECL_WEAK (exp)) + else if (DECL_WEAK (exp) + && !resolved_locally) local_p = false; /* If PIC, then assume that any global name can be overridden by - symbols resolved from other modules, unless we are compiling with - -fwhole-program, which assumes that names are local. */ + symbols resolved from other modules. */ else if (shlib) - local_p = flag_whole_program; + local_p = false; /* Uninitialized COMMON variable may be unified with symbols resolved from other modules. */ else if (DECL_COMMON (exp) + && !resolved_locally && (DECL_INITIAL (exp) == NULL || DECL_INITIAL (exp) == error_mark_node)) local_p = false; @@ -6440,6 +6495,67 @@ default_binds_local_p_1 (const_tree exp, int shlib) return local_p; } +/* Return true when references to DECL must bind to current definition in + final executable. + + The condition is usually equivalent to whether the function binds to the + current module (shared library or executable), that is to binds_local_p. + We use this fact to avoid need for another target hook and implement + the logic using binds_local_p and just special cases where + decl_binds_to_current_def_p is stronger than binds local_p. In particular + the weak definitions (that can be overwritten at linktime by other + definition from different object file) and when resolution info is available + we simply use the knowledge passed to us by linker plugin. */ +bool +decl_binds_to_current_def_p (tree decl) +{ + gcc_assert (DECL_P (decl)); + if (!TREE_PUBLIC (decl)) + return true; + if (!targetm.binds_local_p (decl)) + return false; + /* When resolution is available, just use it. */ + if (TREE_CODE (decl) == VAR_DECL && TREE_PUBLIC (decl) + && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))) + { + struct varpool_node *vnode = varpool_get_node (decl); + if (vnode + && vnode->resolution != LDPR_UNKNOWN) + return resolution_to_local_definition_p (vnode->resolution); + } + else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_PUBLIC (decl)) + { + struct cgraph_node *node = cgraph_get_node_or_alias (decl); + if (node + && node->resolution != LDPR_UNKNOWN) + return resolution_to_local_definition_p (node->resolution); + } + /* Otherwise we have to assume the worst for DECL_WEAK (hidden weaks + binds localy but still can be overwritten). + This rely on fact that binds_local_p behave as decl_replaceable_p + for all other declaration types. */ + return !DECL_WEAK (decl); +} + +/* A replaceable function or variable is one which may be replaced + at link-time with an entirely different definition, provided that the + replacement has the same type. For example, functions declared + with __attribute__((weak)) on most systems are replaceable. + + COMDAT functions are not replaceable, since all definitions of the + function must be equivalent. It is important that COMDAT functions + not be treated as replaceable so that use of C++ template + instantiations is not penalized. */ + +bool +decl_replaceable_p (tree decl) +{ + gcc_assert (DECL_P (decl)); + if (!TREE_PUBLIC (decl) || DECL_COMDAT (decl)) + return false; + return !decl_binds_to_current_def_p (decl); +} + /* Default function to output code that will globalize a label. A target must define GLOBAL_ASM_OP or provide its own function to globalize a label. */ diff --git a/gcc/varpool.c b/gcc/varpool.c index 2b0809456ea..ff3631b3478 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -107,7 +107,7 @@ eq_varpool_node (const void *p1, const void *p2) /* Return varpool node assigned to DECL without creating new one. */ struct varpool_node * -varpool_get_node (tree decl) +varpool_get_node (const_tree decl) { struct varpool_node key, **slot; @@ -116,7 +116,7 @@ varpool_get_node (tree decl) if (!varpool_hash) return NULL; - key.decl = decl; + key.decl = CONST_CAST2 (tree, const_tree, decl); slot = (struct varpool_node **) htab_find_slot (varpool_hash, &key, NO_INSERT); if (!slot) @@ -359,27 +359,37 @@ decide_is_variable_needed (struct varpool_node *node, tree decl) return true; } -/* Return if NODE is constant and its initial value is known (so we can do - constant folding). The decision depends on whole program decisions - and can not be recomputed at ltrans stage for variables from other - partitions. For this reason the new value should be always combined - with the previous knowledge. */ +/* Return if DECL is constant and its initial value is known (so we can do + constant folding using DECL_INITIAL (decl)). */ bool -varpool_decide_const_value_known (struct varpool_node *node) +const_value_known_p (tree decl) { - tree decl = node->decl; + if (TREE_CODE (decl) != VAR_DECL + &&TREE_CODE (decl) != CONST_DECL) + return false; + + if (TREE_CODE (decl) == CONST_DECL + || DECL_IN_CONSTANT_POOL (decl)) + return true; - gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); gcc_assert (TREE_CODE (decl) == VAR_DECL); + if (!TREE_READONLY (decl)) return false; + + /* Gimplifier takes away constructors of local vars */ + if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl)) + return DECL_INITIAL (decl) != NULL; + + gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); + /* Variables declared 'const' without an initializer have zero as the initializer if they may not be overridden at link or run time. */ if (!DECL_INITIAL (decl) && (DECL_EXTERNAL (decl) - || DECL_REPLACEABLE_P (decl))) + || decl_replaceable_p (decl))) return false; /* Variables declared `const' with an initializer are considered @@ -423,7 +433,6 @@ varpool_finalize_decl (tree decl) there. */ else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) varpool_mark_needed_node (node); - node->const_value_known |= varpool_decide_const_value_known (node); if (cgraph_global_info_ready) varpool_assemble_pending_decls (); } @@ -441,7 +450,7 @@ cgraph_variable_initializer_availability (struct varpool_node *node) /* If the variable can be overwritten, return OVERWRITABLE. Takes care of at least two notable extensions - the COMDAT variables used to share template instantiations in C++. */ - if (!(*targetm.binds_local_p) (node->decl) && !DECL_COMDAT (node->decl)) + if (!decl_replaceable_p (node->decl)) return AVAIL_OVERWRITABLE; return AVAIL_AVAILABLE; } @@ -653,7 +662,7 @@ add_new_static_var (tree type) /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. Extra name aliases are output whenever DECL is output. */ -bool +struct varpool_node * varpool_extra_name_alias (tree alias, tree decl) { struct varpool_node key, *alias_node, *decl_node, **slot; @@ -674,7 +683,7 @@ varpool_extra_name_alias (tree alias, tree decl) /* If the varpool_node has been already created, fail. */ if (*slot) - return false; + return NULL; alias_node = ggc_alloc_cleared_varpool_node (); alias_node->decl = alias; @@ -686,7 +695,26 @@ varpool_extra_name_alias (tree alias, tree decl) decl_node->extra_name->prev = alias_node; decl_node->extra_name = alias_node; *slot = alias_node; - return true; + return alias_node; +} + +/* Return true when NODE is known to be used from other (non-LTO) object file. + Known only when doing LTO via linker plugin. */ + +bool +varpool_used_from_object_file_p (struct varpool_node *node) +{ + struct varpool_node *alias; + + if (!TREE_PUBLIC (node->decl)) + return false; + if (resolution_used_from_other_file_p (node->resolution)) + return true; + for (alias = node->extra_name; alias; alias = alias->next) + if (TREE_PUBLIC (alias->decl) + && resolution_used_from_other_file_p (alias->resolution)) + return true; + return false; } #include "gt-varpool.h" diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 248c0b32785..1dc0777d4b0 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,10 @@ +2010-09-21 Iain Sandoe <iains@gcc.gnu.org> + + * Makefile.in (libgcc-extra-parts): Check for static archives and + invoke ranlib after installing them. + (gcc-extra-parts): Likewise. + (install-leaf): Likewise. + 2010-09-14 H.J. Lu <hongjiu.lu@intel.com> * configure: Regenerated. diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index cbca5532f2e..631af5ada04 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -870,6 +870,10 @@ endif for file in $$parts; do \ rm -f $(gcc_objdir)$(MULTISUBDIR)/$$file; \ $(INSTALL_DATA) $$file $(gcc_objdir)$(MULTISUBDIR)/; \ + case $$file in \ + *.a) \ + $(RANLIB) $(gcc_objdir)$(MULTISUBDIR)/$$file ;; \ + esac; \ done # Build extra startfiles in the gcc directory, for unconverted @@ -903,6 +907,10 @@ gcc-extra-parts: for file in $$parts; do \ rm -f $(gcc_objdir)$(MULTISUBDIR)/$$file; \ $(INSTALL_DATA) $$file $(gcc_objdir)$(MULTISUBDIR)/; \ + case $$file in \ + *.a) \ + $(RANLIB) $(gcc_objdir)$(MULTISUBDIR)/$$file ;; \ + esac; \ done all: $(extra-parts) @@ -958,6 +966,10 @@ install-leaf: $(install-shared) $(install-libunwind) for file in $$parts; do \ rm -f $(DESTDIR)$(inst_libdir)/$$file; \ $(INSTALL_DATA) $$file $(DESTDIR)$(inst_libdir)/; \ + case $$file in \ + *.a) \ + $(RANLIB) $(gcc_objdir)$(MULTISUBDIR)/$$file ;; \ + esac; \ done install: install-leaf diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index bd4243f0828..c462a2a5421 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,15 @@ +2010-09-22 Jerry DeLisle <jvdelisle@gcc.gnu.org> + + PR libfortran/45710 + * io/write.c (namelist_write_newline): Pad character array internal + unit records with spaces. + +2010-09-21 Jerry DeLisle <jvdelisle@gcc.gnu.org> + + PR libfortran/45723 + * io/open.c (new_unit): On POSITION_APPEND don't seek if file length is + zero. + 2010-09-14 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR libfortran/45532 @@ -6,7 +18,8 @@ 2010-09-12 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> - * intrinsics/pack_generic.c (pack): Add missing return and fix whitespace. + * intrinsics/pack_generic.c (pack): Add missing return and fix + whitespace. * intrinsics/cshift0.c (cshift0): Fix whitespace. * intrinsics/unpack_generic.c (unpack1, unpack0): Fix whitespace. diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c index be8f4bb0b43..d7448c007f1 100644 --- a/libgfortran/io/open.c +++ b/libgfortran/io/open.c @@ -555,7 +555,7 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags) if (flags->position == POSITION_APPEND) { - if (sseek (u->s, 0, SEEK_END) < 0) + if (file_size (opp->file, opp->file_len) > 0 && sseek (u->s, 0, SEEK_END) < 0) generate_error (&opp->common, LIBERROR_OS, NULL); u->endfile = AT_ENDFILE; } diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c index e811c47baef..fabbaffc9e9 100644 --- a/libgfortran/io/write.c +++ b/libgfortran/io/write.c @@ -1630,6 +1630,20 @@ namelist_write_newline (st_parameter_dt *dtp) { gfc_offset record; int finished; + char *p; + int length = dtp->u.p.current_unit->bytes_left; + + p = write_block (dtp, length); + if (p == NULL) + return; + + if (unlikely (is_char4_unit (dtp))) + { + gfc_char4_t *p4 = (gfc_char4_t *) p; + memset4 (p4, ' ', length); + } + else + memset (p, ' ', length); /* Now that the current record has been padded out, determine where the next record in the array is. */ diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 7079bae6db8..7de7df65fa7 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,10 @@ +2010-09-23 Tobias Burnus <burnus@net-b.de> + + * libgomp.texi (omp_get_nested, omp_set_nested, omp_set_dynamic): + Change Fortran datatype to LOGICAL. + (omp_set_lock, omp_test_lock, omp_unset_lock, omp_set_nested_lock, + omp_unset_nested_lock): Use intent(inout) instead of intent(out). + 2010-08-21 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> * configure: Regenerate. diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index 20ffd672542..b88e9844cce 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -362,7 +362,7 @@ disabled by default. @item @emph{Fortran}: @multitable @columnfractions .20 .80 -@item @emph{Interface}: @tab @code{integer function omp_get_nested()} +@item @emph{Interface}: @tab @code{logical function omp_get_nested()} @end multitable @item @emph{See also}: @@ -583,7 +583,7 @@ adjustment of team sizes and @code{false} disables it. @item @emph{Fortran}: @multitable @columnfractions .20 .80 @item @emph{Interface}: @tab @code{subroutine omp_set_dynamic(set)} -@item @tab @code{integer, intent(in) :: set} +@item @tab @code{logical, intent(in) :: set} @end multitable @item @emph{See also}: @@ -639,7 +639,7 @@ dynamic adjustment of team sizes and @code{false} disables it. @item @emph{Fortran}: @multitable @columnfractions .20 .80 @item @emph{Interface}: @tab @code{subroutine omp_set_nested(set)} -@item @tab @code{integer, intent(in) :: set} +@item @tab @code{logical, intent(in) :: set} @end multitable @item @emph{See also}: @@ -756,7 +756,7 @@ a deadlock occurs. @item @emph{Fortran}: @multitable @columnfractions .20 .80 @item @emph{Interface}: @tab @code{subroutine omp_set_lock(lock)} -@item @tab @code{integer(omp_lock_kind), intent(out) :: lock} +@item @tab @code{integer(omp_lock_kind), intent(inout) :: lock} @end multitable @item @emph{See also}: @@ -787,7 +787,7 @@ does not block if the lock is not available. This function returns @multitable @columnfractions .20 .80 @item @emph{Interface}: @tab @code{subroutine omp_test_lock(lock)} @item @tab @code{logical(omp_logical_kind) :: omp_test_lock} -@item @tab @code{integer(omp_lock_kind), intent(out) :: lock} +@item @tab @code{integer(omp_lock_kind), intent(inout) :: lock} @end multitable @item @emph{See also}: @@ -817,7 +817,7 @@ again, set the lock for itself. @item @emph{Fortran}: @multitable @columnfractions .20 .80 @item @emph{Interface}: @tab @code{subroutine omp_unset_lock(lock)} -@item @tab @code{integer(omp_lock_kind), intent(out) :: lock} +@item @tab @code{integer(omp_lock_kind), intent(inout) :: lock} @end multitable @item @emph{See also}: @@ -899,7 +899,7 @@ nesting count for the lock in incremented. @item @emph{Fortran}: @multitable @columnfractions .20 .80 @item @emph{Interface}: @tab @code{subroutine omp_set_nest_lock(lock)} -@item @tab @code{integer(omp_nest_lock_kind), intent(out) :: lock} +@item @tab @code{integer(omp_nest_lock_kind), intent(inout) :: lock} @end multitable @item @emph{See also}: @@ -961,7 +961,7 @@ one of them is chosen to, again, set the lock for itself. @item @emph{Fortran}: @multitable @columnfractions .20 .80 @item @emph{Interface}: @tab @code{subroutine omp_unset_nest_lock(lock)} -@item @tab @code{integer(omp_nest_lock_kind), intent(out) :: lock} +@item @tab @code{integer(omp_nest_lock_kind), intent(inout) :: lock} @end multitable @item @emph{See also}: diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 7004f861678..77f7fe34752 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,10 @@ +2010-09-22 Tristan Gingold <gingold@adacore.com> + + * cplus-dem.c (ada_demangle): Add comments. + Handle stream and controlled type operations. + Decoding of some uppercase letters moved before separators. + * testsuite/demangle-expected: Add tests. + 2010-09-10 James Lyon <jameslyon0@googlemail.com> http://sourceware.org/bugzilla/show_bug.cgi?id=11572 @@ -5,32 +12,6 @@ DEMANGLE_COMPONENT_LAMBDA. * testsuite/demangle-expected: Add regression test. -diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c -index d2d15e9..39c8cc0 100644 ---- a/libiberty/cp-demangle.c -+++ b/libiberty/cp-demangle.c -@@ -3480,6 +3480,7 @@ d_find_pack (struct d_print_info *dpi, - case DEMANGLE_COMPONENT_PACK_EXPANSION: - return NULL; - -+ case DEMANGLE_COMPONENT_LAMBDA: - case DEMANGLE_COMPONENT_NAME: - case DEMANGLE_COMPONENT_OPERATOR: - case DEMANGLE_COMPONENT_BUILTIN_TYPE: -diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected -index 15a0fe7..0085564 100644 ---- a/libiberty/testsuite/demangle-expected -+++ b/libiberty/testsuite/demangle-expected -@@ -4052,3 +4052,8 @@ prot.lock.update - --format=gnu-v3 - DFA - DFA -+# -+# http://sourceware.org/bugzilla/show_bug.cgi?id=11572 -+--format=auto -+_ZN3Psi7VariantIIcPKcEE5visitIIRZN11VariantTest9TestVisit11test_methodEvEUlS2_E0_RZNS6_11test_methodEvEUlcE1_RZNS6_11test_methodEvEUlNS_4NoneEE_EEENS_13VariantDetail19SelectVisitorResultIIDpT_EE4typeEDpOSG_ -+Psi::VariantDetail::SelectVisitorResult<VariantTest::TestVisit::test_method()::{lambda(char const*)#2}&, VariantTest::TestVisit::test_method()::{lambda(char)#3}&, VariantTest::TestVisit::test_method()::{lambda(Psi::None)#1}&>::type Psi::Variant<char, char const*>::visit<VariantTest::TestVisit::test_method()::{lambda(char const*)#2}&, VariantTest::TestVisit::test_method()::{lambda(char)#3}&, VariantTest::TestVisit::test_method()::{lambda(Psi::None)#1}&>((VariantTest::TestVisit::test_method()::{lambda(Psi::None)#1}&&&)...) - 2010-09-08 Tristan Gingold <gingold@adacore.com> PR 44001 diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index f20a5ef9d84..0d812d5ef83 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -895,18 +895,20 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) /* Most of the demangling will trivially remove chars. Operator names may add one char but because they are always preceeded by '__' which is - replaced by '.', they eventually never expand the size. '___elabs' and - '___elabb' add only 2 chars, but they occur only once. */ - len0 = strlen (mangled) + 2 + 1; + replaced by '.', they eventually never expand the size. + A few special names such as '___elabs' add a few chars (at most 7), but + they occur only once. */ + len0 = strlen (mangled) + 7 + 1; demangled = XNEWVEC (char, len0); d = demangled; p = mangled; while (1) { - /* Convert name, which is always lower-case. */ + /* An entity names is expected. */ if (ISLOWER (*p)) { + /* An identifier, which is always lower case. */ do *d++ = *p++; while (ISLOWER(*p) || ISDIGIT (*p) @@ -914,6 +916,7 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) } else if (p[0] == 'O') { + /* An operator name. */ static const char * const operators[][2] = {{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"}, {"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"}, @@ -924,22 +927,22 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) {"Oexpon", "**"}, {NULL, NULL}}; int k; - for (k = 0; operators[k][0]; k++) + for (k = 0; operators[k][0] != NULL; k++) { - int l = strlen (operators[k][0]); - if (!strncmp (p, operators[k][0], l)) + size_t slen = strlen (operators[k][0]); + if (strncmp (p, operators[k][0], slen) == 0) { - p += l; - l = strlen (operators[k][1]); + p += slen; + slen = strlen (operators[k][1]); *d++ = '"'; - memcpy (d, operators[k][1], l); - d += l; + memcpy (d, operators[k][1], slen); + d += slen; *d++ = '"'; break; } } /* Operator not found. */ - if (!operators[k][0]) + if (operators[k][0] == NULL) goto unknown; } else @@ -948,6 +951,92 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) goto unknown; } + /* The name can be directly followed by some uppercase letters. */ + if (p[0] == 'T' && p[1] == 'K') + { + /* Task stuff. */ + if (p[2] == 'B' && p[3] == 0) + { + /* Subprogram for task body. */ + break; + } + else if (p[2] == '_' && p[3] == '_') + { + /* Inner declarations in a task. */ + p += 4; + *d++ = '.'; + continue; + } + else + goto unknown; + } + if (p[0] == 'E' && p[1] == 0) + { + /* Exception name. */ + goto unknown; + } + if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0) + { + /* Protected type subprogram. */ + break; + } + if ((*p == 'N' || *p == 'S') && p[1] == 0) + { + /* Enumerated type name table. */ + goto unknown; + } + if (p[0] == 'X') + { + /* Body nested. */ + p++; + while (p[0] == 'n' || p[0] == 'b') + p++; + } + if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0)) + { + /* Stream operations. */ + const char *name; + switch (p[1]) + { + case 'R': + name = "'Read"; + break; + case 'W': + name = "'Write"; + break; + case 'I': + name = "'Input"; + break; + case 'O': + name = "'Output"; + break; + default: + goto unknown; + } + p += 2; + strcpy (d, name); + d += strlen (name); + } + else if (p[0] == 'D') + { + /* Controlled type operation. */ + const char *name; + switch (p[1]) + { + case 'F': + name = ".Finalize"; + break; + case 'A': + name = ".Adjust"; + break; + default: + goto unknown; + } + strcpy (d, name); + d += strlen (name); + break; + } + if (p[0] == '_') { /* Separator. */ @@ -955,24 +1044,49 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) { /* Standard separator. Handled first. */ p += 2; + if (ISDIGIT (*p)) { - /* Overloading. */ + /* Overloading number. */ do p++; while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1]))); + if (*p == 'X') + { + p++; + while (p[0] == 'n' || p[0] == 'b') + p++; + } } - else if (*p == '_' && !strcmp (p + 1, "elabb")) - { - memcpy (d, "'Elab_Body", 10); - d += 10; - break; - } - else if (*p == '_' && !strcmp (p + 1, "elabs")) + else if (p[0] == '_' && p[1] != '_') { - memcpy (d, "'Elab_Spec", 10); - d += 10; - break; + /* Special names. */ + static const char * const special[][2] = { + { "_elabb", "'Elab_Body" }, + { "_elabs", "'Elab_Spec" }, + { "_size", "'Size" }, + { "_alignment", "'Alignment" }, + { "_assign", ".\":=\"" }, + { NULL, NULL } + }; + int k; + + for (k = 0; special[k][0] != NULL; k++) + { + size_t slen = strlen (special[k][0]); + if (strncmp (p, special[k][0], slen) == 0) + { + p += slen; + slen = strlen (special[k][1]); + memcpy (d, special[k][1], slen); + d += slen; + break; + } + } + if (special[k][0] != NULL) + break; + else + goto unknown; } else { @@ -995,46 +1109,6 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) goto unknown; } - if (p[0] == 'T' && p[1] == 'K') - { - if (p[2] == 'B' && p[3] == 0) - { - /* Subprogram for task body. */ - break; - } - else if (p[2] == '_' && p[3] == '_') - { - /* Inner declarations in a task. */ - p += 4; - *d++ = '.'; - continue; - } - else - goto unknown; - } - if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0) - { - /* Protected type subprogram. */ - break; - } - if (p[0] == 'E' && p[1] == 0) - { - /* Exception name. */ - goto unknown; - } - if (*p == 'N' || *p == 'S') - { - /* Enumerated type name table. */ - goto unknown; - } - if (p[0] == 'X') - { - /* Body nested. */ - if (p[1] == 'n' || p[1] == 'b') - p += 2; - else if (p[1] == 0) - p++; - } if (p[0] == '.' && ISDIGIT (p[1])) { /* Nested subprogram. */ diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 0085564ae9a..0507ce86651 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -4047,6 +4047,36 @@ prot.lock.update --format=gnat prot__lock__update_E6s prot.lock.update +# Controlled types +--format=gnat +gnat__sockets__sockets_library_controllerDF__2 +gnat.sockets.sockets_library_controller.Finalize +--format=gnat +system__partition_interface__racw_stub_typeDA +system.partition_interface.racw_stub_type.Adjust +# Stream operations +--format=gnat +gnat__wide_wide_string_split__slice_setSR__2 +gnat.wide_wide_string_split.slice_set'Read +--format=gnat +ada__real_time__timing_events__events__listSW__2Xnn +ada.real_time.timing_events.events.list'Write +--format=gnat +system__finalization_root__root_controlledSI +system.finalization_root.root_controlled'Input +--format=gnat +ada__finalization__limited_controlledSO__2 +ada.finalization.limited_controlled'Output +# Tagged types +--format=gnat +ada__synchronous_task_control___size__2 +ada.synchronous_task_control'Size +--format=gnat +ada__real_time__timing_events__events___alignment__2Xnn +ada.real_time.timing_events.events'Alignment +--format=gnat +system__finalization_root___assign__2 +system.finalization_root.":=" # # Used to crash the demangler. --format=gnu-v3 diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 7094149fb2c..11f14b15b34 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,9 @@ +2010-09-21 Jack Howarth <howarth@bromo.med.uc.edu> + + * libjava/configure.ac: Set LIBMATHSPEC to -lm except on darwin. + * libjava/libgcj.spec.in: Use LIBMATHSPEC. + * libjava/configure: Regenerate. + 2010-08-27 Dmitrijs Ledkovs <dmitrij.ledkov@ubuntu.com> Ralf Wildenhues <Ralf.Wildenhues@gmx.de> diff --git a/libjava/configure b/libjava/configure index 8fa4baffd68..80a59d6eeff 100755 --- a/libjava/configure +++ b/libjava/configure @@ -707,6 +707,7 @@ GCDEPS GCINCS GCLIBS LIBGCJTESTSPEC +LIBMATHSPEC LIBSTDCXXSPEC extra_ldflags extra_ldflags_libjava @@ -13353,7 +13354,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 13356 "configure" +#line 13357 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13459,7 +13460,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 13462 "configure" +#line 13463 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -19438,7 +19439,7 @@ if test "${enable_sjlj_exceptions+set}" = set; then : enableval=$enable_sjlj_exceptions; : else cat > conftest.$ac_ext << EOF -#line 19441 "configure" +#line 19442 "configure" struct S { ~S(); }; void bar(); void foo() @@ -20535,6 +20536,16 @@ arm*linux*eabi) ;; esac +LIBMATHSPEC= +# extra LD Flags which are required for targets +case "${host}" in +*-*-darwin*) + ;; +*) + LIBMATHSPEC=-lm + ;; +esac + # Check for --no-merge-exidx-entries, an ARM-specific linker option. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --no-merge-exidx-entries" >&5 $as_echo_n "checking for --no-merge-exidx-entries... " >&6; } @@ -20582,6 +20593,7 @@ fi + # Allow the GC to be disabled. Can be useful when debugging. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for garbage collector to use" >&5 $as_echo_n "checking for garbage collector to use... " >&6; } diff --git a/libjava/configure.ac b/libjava/configure.ac index df6bca3f662..c64f6f3c3dd 100644 --- a/libjava/configure.ac +++ b/libjava/configure.ac @@ -931,6 +931,16 @@ arm*linux*eabi) ;; esac +LIBMATHSPEC= +# extra LD Flags which are required for targets +case "${host}" in +*-*-darwin*) + ;; +*) + LIBMATHSPEC=-lm + ;; +esac + # Check for --no-merge-exidx-entries, an ARM-specific linker option. AC_CACHE_CHECK([for --no-merge-exidx-entries], [libgcj_cv_exidx], [saved_ldflags="$LDFLAGS" @@ -956,6 +966,7 @@ fi AC_SUBST(extra_ldflags_libjava) AC_SUBST(extra_ldflags) AC_SUBST(LIBSTDCXXSPEC) +AC_SUBST(LIBMATHSPEC) AC_SUBST(LIBGCJTESTSPEC) diff --git a/libjava/libgcj.spec.in b/libjava/libgcj.spec.in index 55eb0c2e658..8d39532a4b8 100644 --- a/libjava/libgcj.spec.in +++ b/libjava/libgcj.spec.in @@ -7,6 +7,6 @@ *startfile: @THREADSTARTFILESPEC@ %(startfileorig) %rename lib liborig -*lib: @LD_START_STATIC_SPEC@ @LIBGCJ_SPEC@ @LD_FINISH_STATIC_SPEC@ -lm @LIBICONV@ @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(libgcc) @LIBSTDCXXSPEC@ %(liborig) +*lib: @LD_START_STATIC_SPEC@ @LIBGCJ_SPEC@ @LD_FINISH_STATIC_SPEC@ @LIBMATHSPEC@ @LIBICONV@ @GCSPEC@ @THREADSPEC@ @ZLIBSPEC@ @SYSTEMSPEC@ %(libgcc) @LIBSTDCXXSPEC@ %(liborig) *jc1: @HASH_SYNC_SPEC@ @DIVIDESPEC@ @CHECKREFSPEC@ @JC1GCSPEC@ @EXCEPTIONSPEC@ @BACKTRACESPEC@ @IEEESPEC@ @ATOMICSPEC@ @LIBGCJ_BC_SPEC@ -fkeep-inline-functions diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog index 9022c1b5bc0..f9d9925798a 100644 --- a/libobjc/ChangeLog +++ b/libobjc/ChangeLog @@ -1,3 +1,77 @@ +2010-09-26 Nicola Pero <nicola.pero@meta-innovation.com> + + * libobjc_entry.c: File removed. + +2010-09-26 Kai Tietz <kai.tietz@onevision.com> + + * sendmsg.c (objc_msg_lookup): Remove inline. + (objc_get_uninstalled_dtable): Likewise. + * encoding.c (objc_skip_type_qualifiers): Likewise. + (objc_skip_offset): Likewise. + * archive.c (__objc_write_object): Likewise + (__objc_write_class): + (__objc_write_selector): + (objc_read_char): + (objc_read_unsigned_char): + (objc_read_short): + (objc_read_unsigned_short): + (objc_read_int): + (objc_read_long): + (__objc_read_nbyte_uint): + (objc_read_unsigned_int): + (objc_read_unsigned_long): + * objc/objc-decls.h (obc_EXPORT): Remove dllexport for DLL_EXPORT case. + (objc_EXPORT): Likewise. + * objc/message.h (objc-decls.h): Add include. + * objc/objc-api.h: Mark API by objc_EXPORT. + * libobjc.def (__objc_responds_to): Removed. + +2010-09-18 Nicola Pero <nicola.pero@meta-innovation.com> + + * hash.c: Include objc-private/hash.h instead of objc/hash.h. + + * objc/sarray.h: Moved into objc/deprecated/sarray.h; + objc/sarray.h replaced with a placeholder including the file from + the deprecated/ directory. + * objc-private/sarray.h: New file (private copy of sarray.h). + * hash.c: Include <assert.h> instead of "assert.h" + * sarray.c: Include <assert.h> instead of "assert.h". Include + objc-private/sarray.h instead of objc/sarray.h. + * selector.c: Include objc-private/sarray.h instead of + objc/sarray.h. + * sendmsg.c: Include <assert.h>. Include objc-private/sarray.h + instead of objc/sarray.h. + * Makefile.in (OBJC_DEPRECATED_H): Added sarray.h. + +2010-09-17 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc-private/objc-list.h (list_remove_elem): Unused function + removed. (list_nth): Unused function removed. (list_find): + Unused function removed. (list_lenght): Unused function removed. + +2010-09-17 Nicola Pero <nicola.pero@meta-innovation.com> + + * objc/hash.h: Moved into objc/deprecated/hash.h; objc/hash.h + replaced with a placeholder including the file from the + deprecated/ directory. + * objc/objc-api.h: Updated includes. + * objc/typedstream.h: Updated includes. + * objc-private/hash.h: New file (private copy of hash.h). + * objc/objc-list.h: Moved into objc/deprecated/objc-list.h; + objc/objc-list.h replaced with a placeholder including the file + from the deprecated/ directory. + * objc-private/objc-list.h: New file (private copy of objc-list.h). + * init.c: Include objc-private/hash.h and objc-private/objc-list.h + instead of objc/hash.h and objc/objc-list.h. + * selector.c: Same change. + * class.c: Added include <string.h>, which used to be implicitly included + when hash.h was included. + * exception.c: Same change. + * objects.c: Same change. + * sarray.c: Same change. + * sendmsg.c: Same change. + * Makefile.in (OBJC_DEPRECATED_H): Added hash.h and objc-list.h. + 2010-09-14 Nicola Pero <nicola.pero@meta-innovation.com> Implemented objc_sync_enter() and objc_sync_exit(), which are diff --git a/libobjc/Makefile.in b/libobjc/Makefile.in index 78d5bb01c61..71a3a2e21c2 100644 --- a/libobjc/Makefile.in +++ b/libobjc/Makefile.in @@ -117,14 +117,14 @@ OBJC_H = \ Object.h \ Protocol.h \ encoding.h \ - hash.h \ message.h \ objc-api.h \ objc-decls.h \ - objc-list.h \ - sarray.h \ thr.h \ \ + hash.h \ + objc-list.h \ + sarray.h \ typedstream.h # User-visible header files containing deprecated APIs, from the @@ -133,10 +133,13 @@ OBJC_DEPRECATED_H = \ MetaClass.h \ Object.h \ STR.h \ + hash.h \ + objc-list.h \ objc_error.h \ objc_malloc.h \ objc_unexpected_exception.h \ objc_valloc.h \ + sarray.h \ struct_objc_class.h \ struct_objc_protocol.h \ struct_objc_selector.h \ diff --git a/libobjc/archive.c b/libobjc/archive.c index 9b46976fbf4..f36f1b748fb 100644 --- a/libobjc/archive.c +++ b/libobjc/archive.c @@ -372,7 +372,7 @@ __objc_write_extension (struct objc_typed_stream *stream, unsigned char code) } } -inline int +int __objc_write_object (struct objc_typed_stream *stream, id object) { unsigned char buf = '\0'; @@ -437,7 +437,7 @@ objc_write_object (struct objc_typed_stream *stream, id object) } } -inline int +int __objc_write_class (struct objc_typed_stream *stream, struct objc_class *class) { __objc_write_extension (stream, _BX_CLASS); @@ -466,7 +466,7 @@ objc_write_class (struct objc_typed_stream *stream, } -inline int +int __objc_write_selector (struct objc_typed_stream *stream, SEL selector) { const char *sel_name; @@ -509,7 +509,7 @@ objc_write_selector (struct objc_typed_stream *stream, SEL selector) ** Read operations */ -inline int +int objc_read_char (struct objc_typed_stream *stream, char *val) { unsigned char buf; @@ -535,7 +535,7 @@ objc_read_char (struct objc_typed_stream *stream, char *val) } -inline int +int objc_read_unsigned_char (struct objc_typed_stream *stream, unsigned char *val) { unsigned char buf; @@ -555,7 +555,7 @@ objc_read_unsigned_char (struct objc_typed_stream *stream, unsigned char *val) return len; } -inline int +int objc_read_short (struct objc_typed_stream *stream, short *value) { unsigned char buf[sizeof (short) + 1]; @@ -582,7 +582,7 @@ objc_read_short (struct objc_typed_stream *stream, short *value) return len; } -inline int +int objc_read_unsigned_short (struct objc_typed_stream *stream, unsigned short *value) { @@ -609,7 +609,7 @@ objc_read_unsigned_short (struct objc_typed_stream *stream, } -inline int +int objc_read_int (struct objc_typed_stream *stream, int *value) { unsigned char buf[sizeof (int) + 1]; @@ -636,7 +636,7 @@ objc_read_int (struct objc_typed_stream *stream, int *value) return len; } -inline int +int objc_read_long (struct objc_typed_stream *stream, long *value) { unsigned char buf[sizeof (long) + 1]; @@ -663,7 +663,7 @@ objc_read_long (struct objc_typed_stream *stream, long *value) return len; } -inline int +int __objc_read_nbyte_uint (struct objc_typed_stream *stream, unsigned int nbytes, unsigned int *val) { @@ -682,7 +682,7 @@ __objc_read_nbyte_uint (struct objc_typed_stream *stream, } -inline int +int objc_read_unsigned_int (struct objc_typed_stream *stream, unsigned int *value) { @@ -719,7 +719,7 @@ __objc_read_nbyte_ulong (struct objc_typed_stream *stream, } -inline int +int objc_read_unsigned_long (struct objc_typed_stream *stream, unsigned long *value) { @@ -737,7 +737,7 @@ objc_read_unsigned_long (struct objc_typed_stream *stream, return len; } -inline int +int objc_read_string (struct objc_typed_stream *stream, char **string) { diff --git a/libobjc/class.c b/libobjc/class.c index 76f9e8feecd..cba9b843355 100644 --- a/libobjc/class.c +++ b/libobjc/class.c @@ -93,6 +93,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc/objc-api.h" #include "objc/thr.h" #include "objc-private/runtime.h" /* the kitchen sink */ +#include <string.h> /* For memset */ /* We use a table which maps a class name to the corresponding class * pointer. The first part of this file defines this table, and diff --git a/libobjc/encoding.c b/libobjc/encoding.c index c0d79d9f349..35c95521b80 100644 --- a/libobjc/encoding.c +++ b/libobjc/encoding.c @@ -563,7 +563,7 @@ objc_promoted_size (const char *type) occurring in method prototype encodings. */ -inline const char * +const char * objc_skip_type_qualifiers (const char *type) { while (*type == _C_CONST @@ -701,7 +701,7 @@ objc_skip_typespec (const char *type) Skip an offset as part of a method encoding. This is prepended by a '+' if the argument is passed in registers. */ -inline const char * +const char * objc_skip_offset (const char *type) { if (*type == '+') diff --git a/libobjc/exception.c b/libobjc/exception.c index bb6a9194af1..0225d6789a4 100644 --- a/libobjc/exception.c +++ b/libobjc/exception.c @@ -29,6 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc/objc-exception.h" #include "unwind.h" #include "unwind-pe.h" +#include <string.h> /* For memcpy */ /* This hook allows libraries to sepecify special actions when an exception is thrown without a handler in place. This is deprecated diff --git a/libobjc/hash.c b/libobjc/hash.c index 9e0a608c130..602fc84a874 100644 --- a/libobjc/hash.c +++ b/libobjc/hash.c @@ -23,11 +23,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ #include "objc-private/common.h" -#include "assert.h" +#include <assert.h> /* For assert */ #include "objc/objc.h" #include "objc/objc-api.h" -#include "objc/hash.h" +#include "objc-private/hash.h" #include "objc-private/runtime.h" /* for DEBUG_PRINTF */ /* These two macros determine when a hash table is full and diff --git a/libobjc/init.c b/libobjc/init.c index 206b85b5c0d..deb089d7e16 100644 --- a/libobjc/init.c +++ b/libobjc/init.c @@ -29,8 +29,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc/objc.h" #include "objc/objc-api.h" #include "objc/thr.h" -#include "objc/hash.h" -#include "objc/objc-list.h" +#include "objc-private/hash.h" +#include "objc-private/objc-list.h" #include "objc-private/runtime.h" #include "objc-private/objc-sync.h" /* For __objc_sync_init() */ diff --git a/libobjc/libobjc.def b/libobjc/libobjc.def index 2d27fa5dce3..ee323388a0c 100644 --- a/libobjc/libobjc.def +++ b/libobjc/libobjc.def @@ -132,7 +132,6 @@ __objc_exec_class __objc_init_dispatch_tables __objc_install_premature_dtable __objc_print_dtable_stats -__objc_responds_to __objc_update_dispatch_table_for_class class_add_method_list class_get_class_method diff --git a/libobjc/libobjc_entry.c b/libobjc/libobjc_entry.c deleted file mode 100644 index 5cbc89c4f13..00000000000 --- a/libobjc/libobjc_entry.c +++ /dev/null @@ -1,54 +0,0 @@ -/* GNU Objective C Runtime DLL Entry - Copyright (C) 1997, 2009 Free Software Foundation, Inc. - Contributed by Scott Christley <scottc@net-community.com> - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3, 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. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - -#include "objc-private/common.h" -#include <windows.h> - -/* - DLL entry function for Objective-C Runtime library - This function gets called everytime a process/thread attaches to DLL - */ -WINBOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, - LPVOID lpReserved) -{ - switch(ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - break; - case DLL_PROCESS_DETACH: - break; - case DLL_THREAD_ATTACH: - break; - case DLL_THREAD_DETACH: - break; - } - return TRUE; -} - -/* - This section terminates the list of imports under GCC. If you do not - include this then you will have problems when linking with DLLs. - */ -asm (".section .idata$3\n" ".long 0,0,0,0,0,0,0,0"); diff --git a/libobjc/objc-private/hash.h b/libobjc/objc-private/hash.h new file mode 100644 index 00000000000..7c57a4d2589 --- /dev/null +++ b/libobjc/objc-private/hash.h @@ -0,0 +1,214 @@ +/* Hash tables for Objective C method dispatch. + Copyright (C) 1993, 1995, 1996, 2004, 2009 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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +/* You need to include this file after including objc.h */ + +#ifndef __hash_INCLUDE_GNU +#define __hash_INCLUDE_GNU + +#include <stddef.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * This data structure is used to hold items + * stored in a hash table. Each node holds + * a key/value pair. + * + * Items in the cache are really of type void *. + */ +typedef struct cache_node +{ + struct cache_node *next; /* Pointer to next entry on the list. + NULL indicates end of list. */ + const void *key; /* Key used to locate the value. Used + to locate value when more than one + key computes the same hash + value. */ + void *value; /* Value stored for the key. */ +} *node_ptr; + + +/* + * This data type is the function that computes a hash code given a key. + * Therefore, the key can be a pointer to anything and the function specific + * to the key type. + * + * Unfortunately there is a mutual data structure reference problem with this + * typedef. Therefore, to remove compiler warnings the functions passed to + * objc_hash_new will have to be casted to this type. + */ +typedef unsigned int (*hash_func_type) (void *, const void *); + +/* + * This data type is the function that compares two hash keys and returns an + * integer greater than, equal to, or less than 0, according as the first + * parameter is lexicographically greater than, equal to, or less than the + * second. + */ + +typedef int (*compare_func_type) (const void *, const void *); + + +/* + * This data structure is the cache. + * + * It must be passed to all of the hashing routines + * (except for new). + */ +typedef struct cache +{ + /* Variables used to implement the hash itself. */ + node_ptr *node_table; /* Pointer to an array of hash nodes. */ + /* Variables used to track the size of the hash table so to determine + when to resize it. */ + unsigned int size; /* Number of buckets allocated for the hash table + (number of array entries allocated for + "node_table"). Must be a power of two. */ + unsigned int used; /* Current number of entries in the hash table. */ + unsigned int mask; /* Precomputed mask. */ + + /* Variables used to implement indexing through the hash table. */ + + unsigned int last_bucket; /* Tracks which entry in the array where + the last value was returned. */ + /* Function used to compute a hash code given a key. + This function is specified when the hash table is created. */ + hash_func_type hash_func; + /* Function used to compare two hash keys to see if they are equal. */ + compare_func_type compare_func; +} *cache_ptr; + + +/* Two important hash tables. */ +extern cache_ptr module_hash_table, class_hash_table; + +/* Allocate and initialize a hash table. */ + +cache_ptr objc_hash_new (unsigned int size, + hash_func_type hash_func, + compare_func_type compare_func); + +/* Deallocate all of the hash nodes and the cache itself. */ + +void objc_hash_delete (cache_ptr cache); + +/* Add the key/value pair to the hash table. If the + hash table reaches a level of fullness then it will be resized. + + assert if the key is already in the hash. */ + +void objc_hash_add (cache_ptr *cachep, const void *key, void *value); + +/* Remove the key/value pair from the hash table. + assert if the key isn't in the table. */ + +void objc_hash_remove (cache_ptr cache, const void *key); + +/* Used to index through the hash table. Start with NULL + to get the first entry. + + Successive calls pass the value returned previously. + ** Don't modify the hash during this operation *** + + Cache nodes are returned such that key or value can + be extracted. */ + +node_ptr objc_hash_next (cache_ptr cache, node_ptr node); + +/* Used to return a value from a hash table using a given key. */ + +void *objc_hash_value_for_key (cache_ptr cache, const void *key); + +/* Used to determine if the given key exists in the hash table */ + +BOOL objc_hash_is_key_in_hash (cache_ptr cache, const void *key); + +/************************************************ + + Useful hashing functions. + + Declared inline for your pleasure. + +************************************************/ + +/* Calculate a hash code by performing some + manipulation of the key pointer. (Use the lowest bits + except for those likely to be 0 due to alignment.) */ + +static inline unsigned int +objc_hash_ptr (cache_ptr cache, const void *key) +{ + return ((size_t)key / sizeof (void *)) & cache->mask; +} + + +/* Calculate a hash code by iterating over a NULL + terminate string. */ +static inline unsigned int +objc_hash_string (cache_ptr cache, const void *key) +{ + unsigned int ret = 0; + unsigned int ctr = 0; + const char *ckey = (const char *) key; + + while (*ckey) { + ret ^= *ckey++ << ctr; + ctr = (ctr + 1) % sizeof (void *); + } + + return ret & cache->mask; +} + + +/* Compare two pointers for equality. */ +static inline int +objc_compare_ptrs (const void *k1, const void *k2) +{ + return (k1 == k2); +} + + +/* Compare two strings. */ +static inline int +objc_compare_strings (const void *k1, const void *k2) +{ + if (k1 == k2) + return 1; + else if (k1 == 0 || k2 == 0) + return 0; + else + return ! strcmp ((const char *) k1, (const char *) k2); +} + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* not __hash_INCLUDE_GNU */ diff --git a/libobjc/objc-private/objc-list.h b/libobjc/objc-private/objc-list.h new file mode 100644 index 00000000000..b78f4c1347f --- /dev/null +++ b/libobjc/objc-private/objc-list.h @@ -0,0 +1,99 @@ +/* Generic single linked list to keep various information + Copyright (C) 1993, 1994, 1996, 2009 Free Software Foundation, Inc. + Contributed by Kresten Krab Thorup. + +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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + + +#ifndef __GNU_OBJC_LIST_H +#define __GNU_OBJC_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct objc_list { + void *head; + struct objc_list *tail; +}; + +/* Return a cons cell produced from (head . tail) */ + +static inline struct objc_list* +list_cons(void* head, struct objc_list* tail) +{ + struct objc_list* cell; + + cell = (struct objc_list*)objc_malloc(sizeof(struct objc_list)); + cell->head = head; + cell->tail = tail; + return cell; +} + +/* Remove the element at the head by replacing it by its successor */ + +static inline void +list_remove_head(struct objc_list** list) +{ + if ((*list)->tail) + { + struct objc_list* tail = (*list)->tail; /* fetch next */ + *(*list) = *tail; /* copy next to list head */ + objc_free(tail); /* free next */ + } + else /* only one element in list */ + { + objc_free(*list); + (*list) = 0; + } +} + + +/* Map FUNCTION over all elements in LIST */ + +static inline void +list_mapcar(struct objc_list* list, void(*function)(void*)) +{ + while(list) + { + (*function)(list->head); + list = list->tail; + } +} + +/* Free list (backwards recursive) */ + +static inline void +list_free(struct objc_list* list) +{ + if(list) + { + list_free(list->tail); + objc_free(list); + } +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* not __GNU_OBJC_LIST_H */ diff --git a/libobjc/objc-private/sarray.h b/libobjc/objc-private/sarray.h new file mode 100644 index 00000000000..f81b08e71e7 --- /dev/null +++ b/libobjc/objc-private/sarray.h @@ -0,0 +1,239 @@ +/* Sparse Arrays for Objective C dispatch tables + Copyright (C) 1993, 1995, 1996, 2004, 2009 Free Software Foundation, Inc. + Contributed by Kresten Krab Thorup. + +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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +#ifndef __sarray_INCLUDE_GNU +#define __sarray_INCLUDE_GNU + +#define OBJC_SPARSE2 /* 2-level sparse array */ +/* #define OBJC_SPARSE3 */ /* 3-level sparse array */ + +#ifdef OBJC_SPARSE2 +extern const char* __objc_sparse2_id; +#endif + +#ifdef OBJC_SPARSE3 +extern const char* __objc_sparse3_id; +#endif + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern int nbuckets; /* for stats */ +extern int nindices; +extern int narrays; +extern int idxsize; + +/* An unsigned integer of same size as a pointer */ +#define SIZET_BITS (sizeof(size_t)*8) + +#if defined(__sparc__) || defined(OBJC_SPARSE2) +#define PRECOMPUTE_SELECTORS +#endif + +#ifdef OBJC_SPARSE3 + +/* Buckets are 8 words each */ +#define BUCKET_BITS 3 +#define BUCKET_SIZE (1<<BUCKET_BITS) +#define BUCKET_MASK (BUCKET_SIZE-1) + +/* Indices are 16 words each */ +#define INDEX_BITS 4 +#define INDEX_SIZE (1<<INDEX_BITS) +#define INDEX_MASK (INDEX_SIZE-1) + +#define INDEX_CAPACITY (BUCKET_SIZE*INDEX_SIZE) + +#else /* OBJC_SPARSE2 */ + +/* Buckets are 32 words each */ +#define BUCKET_BITS 5 +#define BUCKET_SIZE (1<<BUCKET_BITS) +#define BUCKET_MASK (BUCKET_SIZE-1) + +#endif /* OBJC_SPARSE2 */ + +typedef size_t sidx; + +#ifdef PRECOMPUTE_SELECTORS + +struct soffset { +#ifdef OBJC_SPARSE3 + unsigned int unused : SIZET_BITS/4; + unsigned int eoffset : SIZET_BITS/4; + unsigned int boffset : SIZET_BITS/4; + unsigned int ioffset : SIZET_BITS/4; +#else /* OBJC_SPARSE2 */ +#ifdef __sparc__ + unsigned long boffset : (SIZET_BITS - 2) - BUCKET_BITS; + unsigned int eoffset : BUCKET_BITS; + unsigned int unused : 2; +#else + unsigned int boffset : SIZET_BITS/2; + unsigned int eoffset : SIZET_BITS/2; +#endif +#endif /* OBJC_SPARSE2 */ +}; + +union sofftype { + struct soffset off; + sidx idx; +}; + +#endif /* not PRECOMPUTE_SELECTORS */ + +union sversion { + int version; + void *next_free; +}; + +struct sbucket { + void* elems[BUCKET_SIZE]; /* elements stored in array */ + union sversion version; /* used for copy-on-write */ +}; + +#ifdef OBJC_SPARSE3 + +struct sindex { + struct sbucket* buckets[INDEX_SIZE]; + union sversion version; /* used for copy-on-write */ +}; + +#endif /* OBJC_SPARSE3 */ + +struct sarray { +#ifdef OBJC_SPARSE3 + struct sindex** indices; + struct sindex* empty_index; +#else /* OBJC_SPARSE2 */ + struct sbucket** buckets; +#endif /* OBJC_SPARSE2 */ + struct sbucket* empty_bucket; + union sversion version; /* used for copy-on-write */ + short ref_count; + struct sarray* is_copy_of; + size_t capacity; +}; + +struct sarray* sarray_new(int, void* default_element); +void sarray_free(struct sarray*); +struct sarray* sarray_lazy_copy(struct sarray*); +void sarray_realloc(struct sarray*, int new_size); +void sarray_at_put(struct sarray*, sidx indx, void* elem); +void sarray_at_put_safe(struct sarray*, sidx indx, void* elem); + +struct sarray* sarray_hard_copy(struct sarray*); /* ... like the name? */ +void sarray_remove_garbage(void); + + +#ifdef PRECOMPUTE_SELECTORS +/* Transform soffset values to ints and vica verca */ +static inline unsigned int +soffset_decode(sidx indx) +{ + union sofftype x; + x.idx = indx; +#ifdef OBJC_SPARSE3 + return x.off.eoffset + + (x.off.boffset*BUCKET_SIZE) + + (x.off.ioffset*INDEX_CAPACITY); +#else /* OBJC_SPARSE2 */ + return x.off.eoffset + (x.off.boffset*BUCKET_SIZE); +#endif /* OBJC_SPARSE2 */ +} + +static inline sidx +soffset_encode(size_t offset) +{ + union sofftype x; + x.off.eoffset = offset%BUCKET_SIZE; +#ifdef OBJC_SPARSE3 + x.off.boffset = (offset/BUCKET_SIZE)%INDEX_SIZE; + x.off.ioffset = offset/INDEX_CAPACITY; +#else /* OBJC_SPARSE2 */ + x.off.boffset = offset/BUCKET_SIZE; +#endif + return (sidx)x.idx; +} + +#else /* not PRECOMPUTE_SELECTORS */ + +static inline size_t +soffset_decode(sidx indx) +{ + return indx; +} + +static inline sidx +soffset_encode(size_t offset) +{ + return offset; +} +#endif /* not PRECOMPUTE_SELECTORS */ + +/* Get element from the Sparse array `array' at offset `indx' */ + +static inline void* sarray_get(struct sarray* array, sidx indx) +{ +#ifdef PRECOMPUTE_SELECTORS + union sofftype x; + x.idx = indx; +#ifdef OBJC_SPARSE3 + return + array-> + indices[x.off.ioffset]-> + buckets[x.off.boffset]-> + elems[x.off.eoffset]; +#else /* OBJC_SPARSE2 */ + return array->buckets[x.off.boffset]->elems[x.off.eoffset]; +#endif /* OBJC_SPARSE2 */ +#else /* not PRECOMPUTE_SELECTORS */ +#ifdef OBJC_SPARSE3 + return array-> + indices[indx/INDEX_CAPACITY]-> + buckets[(indx/BUCKET_SIZE)%INDEX_SIZE]-> + elems[indx%BUCKET_SIZE]; +#else /* OBJC_SPARSE2 */ + return array->buckets[indx/BUCKET_SIZE]->elems[indx%BUCKET_SIZE]; +#endif /* not OBJC_SPARSE3 */ +#endif /* not PRECOMPUTE_SELECTORS */ +} + +static inline void* sarray_get_safe(struct sarray* array, sidx indx) +{ + if(soffset_decode(indx) < array->capacity) + return sarray_get(array, indx); + else + return (array->empty_bucket->elems[0]); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __sarray_INCLUDE_GNU */ diff --git a/libobjc/objc/deprecated/hash.h b/libobjc/objc/deprecated/hash.h new file mode 100644 index 00000000000..52ee8c31345 --- /dev/null +++ b/libobjc/objc/deprecated/hash.h @@ -0,0 +1,214 @@ +/* Hash tables for Objective C method dispatch. + Copyright (C) 1993, 1995, 1996, 2004, 2009 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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + + + +#ifndef __hash_INCLUDE_GNU +#define __hash_INCLUDE_GNU + +#include <stddef.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * This data structure is used to hold items + * stored in a hash table. Each node holds + * a key/value pair. + * + * Items in the cache are really of type void *. + */ +typedef struct cache_node +{ + struct cache_node *next; /* Pointer to next entry on the list. + NULL indicates end of list. */ + const void *key; /* Key used to locate the value. Used + to locate value when more than one + key computes the same hash + value. */ + void *value; /* Value stored for the key. */ +} *node_ptr; + + +/* + * This data type is the function that computes a hash code given a key. + * Therefore, the key can be a pointer to anything and the function specific + * to the key type. + * + * Unfortunately there is a mutual data structure reference problem with this + * typedef. Therefore, to remove compiler warnings the functions passed to + * objc_hash_new will have to be casted to this type. + */ +typedef unsigned int (*hash_func_type) (void *, const void *); + +/* + * This data type is the function that compares two hash keys and returns an + * integer greater than, equal to, or less than 0, according as the first + * parameter is lexicographically greater than, equal to, or less than the + * second. + */ + +typedef int (*compare_func_type) (const void *, const void *); + + +/* + * This data structure is the cache. + * + * It must be passed to all of the hashing routines + * (except for new). + */ +typedef struct cache +{ + /* Variables used to implement the hash itself. */ + node_ptr *node_table; /* Pointer to an array of hash nodes. */ + /* Variables used to track the size of the hash table so to determine + when to resize it. */ + unsigned int size; /* Number of buckets allocated for the hash table + (number of array entries allocated for + "node_table"). Must be a power of two. */ + unsigned int used; /* Current number of entries in the hash table. */ + unsigned int mask; /* Precomputed mask. */ + + /* Variables used to implement indexing through the hash table. */ + + unsigned int last_bucket; /* Tracks which entry in the array where + the last value was returned. */ + /* Function used to compute a hash code given a key. + This function is specified when the hash table is created. */ + hash_func_type hash_func; + /* Function used to compare two hash keys to see if they are equal. */ + compare_func_type compare_func; +} *cache_ptr; + + +/* Two important hash tables. */ +extern cache_ptr module_hash_table, class_hash_table; + +/* Allocate and initialize a hash table. */ + +cache_ptr objc_hash_new (unsigned int size, + hash_func_type hash_func, + compare_func_type compare_func); + +/* Deallocate all of the hash nodes and the cache itself. */ + +void objc_hash_delete (cache_ptr cache); + +/* Add the key/value pair to the hash table. If the + hash table reaches a level of fullness then it will be resized. + + assert if the key is already in the hash. */ + +void objc_hash_add (cache_ptr *cachep, const void *key, void *value); + +/* Remove the key/value pair from the hash table. + assert if the key isn't in the table. */ + +void objc_hash_remove (cache_ptr cache, const void *key); + +/* Used to index through the hash table. Start with NULL + to get the first entry. + + Successive calls pass the value returned previously. + ** Don't modify the hash during this operation *** + + Cache nodes are returned such that key or value can + be extracted. */ + +node_ptr objc_hash_next (cache_ptr cache, node_ptr node); + +/* Used to return a value from a hash table using a given key. */ + +void *objc_hash_value_for_key (cache_ptr cache, const void *key); + +/* Used to determine if the given key exists in the hash table */ + +BOOL objc_hash_is_key_in_hash (cache_ptr cache, const void *key); + +/************************************************ + + Useful hashing functions. + + Declared inline for your pleasure. + +************************************************/ + +/* Calculate a hash code by performing some + manipulation of the key pointer. (Use the lowest bits + except for those likely to be 0 due to alignment.) */ + +static inline unsigned int +objc_hash_ptr (cache_ptr cache, const void *key) +{ + return ((size_t)key / sizeof (void *)) & cache->mask; +} + + +/* Calculate a hash code by iterating over a NULL + terminate string. */ +static inline unsigned int +objc_hash_string (cache_ptr cache, const void *key) +{ + unsigned int ret = 0; + unsigned int ctr = 0; + const char *ckey = (const char *) key; + + while (*ckey) { + ret ^= *ckey++ << ctr; + ctr = (ctr + 1) % sizeof (void *); + } + + return ret & cache->mask; +} + + +/* Compare two pointers for equality. */ +static inline int +objc_compare_ptrs (const void *k1, const void *k2) +{ + return (k1 == k2); +} + + +/* Compare two strings. */ +static inline int +objc_compare_strings (const void *k1, const void *k2) +{ + if (k1 == k2) + return 1; + else if (k1 == 0 || k2 == 0) + return 0; + else + return ! strcmp ((const char *) k1, (const char *) k2); +} + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* not __hash_INCLUDE_GNU */ diff --git a/libobjc/objc/deprecated/objc-list.h b/libobjc/objc/deprecated/objc-list.h new file mode 100644 index 00000000000..e542bfc0498 --- /dev/null +++ b/libobjc/objc/deprecated/objc-list.h @@ -0,0 +1,155 @@ +/* Generic single linked list to keep various information + Copyright (C) 1993, 1994, 1996, 2009 Free Software Foundation, Inc. + Contributed by Kresten Krab Thorup. + +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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + + +#ifndef __GNU_OBJC_LIST_H +#define __GNU_OBJC_LIST_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct objc_list { + void *head; + struct objc_list *tail; +}; + +/* Return a cons cell produced from (head . tail) */ + +static inline struct objc_list* +list_cons(void* head, struct objc_list* tail) +{ + struct objc_list* cell; + + cell = (struct objc_list*)objc_malloc(sizeof(struct objc_list)); + cell->head = head; + cell->tail = tail; + return cell; +} + +/* Return the length of a list, list_length(NULL) returns zero */ + +static inline int +list_length(struct objc_list* list) +{ + int i = 0; + while(list) + { + i += 1; + list = list->tail; + } + return i; +} + +/* Return the Nth element of LIST, where N count from zero. If N + larger than the list length, NULL is returned */ + +static inline void* +list_nth(int indx, struct objc_list* list) +{ + while(indx-- != 0) + { + if(list->tail) + list = list->tail; + else + return 0; + } + return list->head; +} + +/* Remove the element at the head by replacing it by its successor */ + +static inline void +list_remove_head(struct objc_list** list) +{ + if ((*list)->tail) + { + struct objc_list* tail = (*list)->tail; /* fetch next */ + *(*list) = *tail; /* copy next to list head */ + objc_free(tail); /* free next */ + } + else /* only one element in list */ + { + objc_free(*list); + (*list) = 0; + } +} + + +/* Remove the element with `car' set to ELEMENT */ + +static inline void +list_remove_elem(struct objc_list** list, void* elem) +{ + while (*list) { + if ((*list)->head == elem) + list_remove_head(list); + list = &((*list)->tail); + } +} + +/* Map FUNCTION over all elements in LIST */ + +static inline void +list_mapcar(struct objc_list* list, void(*function)(void*)) +{ + while(list) + { + (*function)(list->head); + list = list->tail; + } +} + +/* Return element that has ELEM as car */ + +static inline struct objc_list** +list_find(struct objc_list** list, void* elem) +{ + while(*list) + { + if ((*list)->head == elem) + return list; + list = &((*list)->tail); + } + return NULL; +} + +/* Free list (backwards recursive) */ + +static inline void +list_free(struct objc_list* list) +{ + if(list) + { + list_free(list->tail); + objc_free(list); + } +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* not __GNU_OBJC_LIST_H */ diff --git a/libobjc/objc/deprecated/sarray.h b/libobjc/objc/deprecated/sarray.h new file mode 100644 index 00000000000..aa2f3350a45 --- /dev/null +++ b/libobjc/objc/deprecated/sarray.h @@ -0,0 +1,240 @@ +/* Sparse Arrays for Objective C dispatch tables + Copyright (C) 1993, 1995, 1996, 2004, 2009 Free Software Foundation, Inc. + Contributed by Kresten Krab Thorup. + +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 3, 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + + +#ifndef __sarray_INCLUDE_GNU +#define __sarray_INCLUDE_GNU + +#define OBJC_SPARSE2 /* 2-level sparse array */ +/* #define OBJC_SPARSE3 */ /* 3-level sparse array */ + +#ifdef OBJC_SPARSE2 +extern const char* __objc_sparse2_id; +#endif + +#ifdef OBJC_SPARSE3 +extern const char* __objc_sparse3_id; +#endif + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern int nbuckets; /* for stats */ +extern int nindices; +extern int narrays; +extern int idxsize; + +/* An unsigned integer of same size as a pointer */ +#define SIZET_BITS (sizeof(size_t)*8) + +#if defined(__sparc__) || defined(OBJC_SPARSE2) +#define PRECOMPUTE_SELECTORS +#endif + +#ifdef OBJC_SPARSE3 + +/* Buckets are 8 words each */ +#define BUCKET_BITS 3 +#define BUCKET_SIZE (1<<BUCKET_BITS) +#define BUCKET_MASK (BUCKET_SIZE-1) + +/* Indices are 16 words each */ +#define INDEX_BITS 4 +#define INDEX_SIZE (1<<INDEX_BITS) +#define INDEX_MASK (INDEX_SIZE-1) + +#define INDEX_CAPACITY (BUCKET_SIZE*INDEX_SIZE) + +#else /* OBJC_SPARSE2 */ + +/* Buckets are 32 words each */ +#define BUCKET_BITS 5 +#define BUCKET_SIZE (1<<BUCKET_BITS) +#define BUCKET_MASK (BUCKET_SIZE-1) + +#endif /* OBJC_SPARSE2 */ + +typedef size_t sidx; + +#ifdef PRECOMPUTE_SELECTORS + +struct soffset { +#ifdef OBJC_SPARSE3 + unsigned int unused : SIZET_BITS/4; + unsigned int eoffset : SIZET_BITS/4; + unsigned int boffset : SIZET_BITS/4; + unsigned int ioffset : SIZET_BITS/4; +#else /* OBJC_SPARSE2 */ +#ifdef __sparc__ + unsigned long boffset : (SIZET_BITS - 2) - BUCKET_BITS; + unsigned int eoffset : BUCKET_BITS; + unsigned int unused : 2; +#else + unsigned int boffset : SIZET_BITS/2; + unsigned int eoffset : SIZET_BITS/2; +#endif +#endif /* OBJC_SPARSE2 */ +}; + +union sofftype { + struct soffset off; + sidx idx; +}; + +#endif /* not PRECOMPUTE_SELECTORS */ + +union sversion { + int version; + void *next_free; +}; + +struct sbucket { + void* elems[BUCKET_SIZE]; /* elements stored in array */ + union sversion version; /* used for copy-on-write */ +}; + +#ifdef OBJC_SPARSE3 + +struct sindex { + struct sbucket* buckets[INDEX_SIZE]; + union sversion version; /* used for copy-on-write */ +}; + +#endif /* OBJC_SPARSE3 */ + +struct sarray { +#ifdef OBJC_SPARSE3 + struct sindex** indices; + struct sindex* empty_index; +#else /* OBJC_SPARSE2 */ + struct sbucket** buckets; +#endif /* OBJC_SPARSE2 */ + struct sbucket* empty_bucket; + union sversion version; /* used for copy-on-write */ + short ref_count; + struct sarray* is_copy_of; + size_t capacity; +}; + +struct sarray* sarray_new(int, void* default_element); +void sarray_free(struct sarray*); +struct sarray* sarray_lazy_copy(struct sarray*); +void sarray_realloc(struct sarray*, int new_size); +void sarray_at_put(struct sarray*, sidx indx, void* elem); +void sarray_at_put_safe(struct sarray*, sidx indx, void* elem); + +struct sarray* sarray_hard_copy(struct sarray*); /* ... like the name? */ +void sarray_remove_garbage(void); + + +#ifdef PRECOMPUTE_SELECTORS +/* Transform soffset values to ints and vica verca */ +static inline unsigned int +soffset_decode(sidx indx) +{ + union sofftype x; + x.idx = indx; +#ifdef OBJC_SPARSE3 + return x.off.eoffset + + (x.off.boffset*BUCKET_SIZE) + + (x.off.ioffset*INDEX_CAPACITY); +#else /* OBJC_SPARSE2 */ + return x.off.eoffset + (x.off.boffset*BUCKET_SIZE); +#endif /* OBJC_SPARSE2 */ +} + +static inline sidx +soffset_encode(size_t offset) +{ + union sofftype x; + x.off.eoffset = offset%BUCKET_SIZE; +#ifdef OBJC_SPARSE3 + x.off.boffset = (offset/BUCKET_SIZE)%INDEX_SIZE; + x.off.ioffset = offset/INDEX_CAPACITY; +#else /* OBJC_SPARSE2 */ + x.off.boffset = offset/BUCKET_SIZE; +#endif + return (sidx)x.idx; +} + +#else /* not PRECOMPUTE_SELECTORS */ + +static inline size_t +soffset_decode(sidx indx) +{ + return indx; +} + +static inline sidx +soffset_encode(size_t offset) +{ + return offset; +} +#endif /* not PRECOMPUTE_SELECTORS */ + +/* Get element from the Sparse array `array' at offset `indx' */ + +static inline void* sarray_get(struct sarray* array, sidx indx) +{ +#ifdef PRECOMPUTE_SELECTORS + union sofftype x; + x.idx = indx; +#ifdef OBJC_SPARSE3 + return + array-> + indices[x.off.ioffset]-> + buckets[x.off.boffset]-> + elems[x.off.eoffset]; +#else /* OBJC_SPARSE2 */ + return array->buckets[x.off.boffset]->elems[x.off.eoffset]; +#endif /* OBJC_SPARSE2 */ +#else /* not PRECOMPUTE_SELECTORS */ +#ifdef OBJC_SPARSE3 + return array-> + indices[indx/INDEX_CAPACITY]-> + buckets[(indx/BUCKET_SIZE)%INDEX_SIZE]-> + elems[indx%BUCKET_SIZE]; +#else /* OBJC_SPARSE2 */ + return array->buckets[indx/BUCKET_SIZE]->elems[indx%BUCKET_SIZE]; +#endif /* not OBJC_SPARSE3 */ +#endif /* not PRECOMPUTE_SELECTORS */ +} + +static inline void* sarray_get_safe(struct sarray* array, sidx indx) +{ + if(soffset_decode(indx) < array->capacity) + return sarray_get(array, indx); + else + return (array->empty_bucket->elems[0]); +} + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __sarray_INCLUDE_GNU */ diff --git a/libobjc/objc/hash.h b/libobjc/objc/hash.h index 146abd97faa..8225a0992e4 100644 --- a/libobjc/objc/hash.h +++ b/libobjc/objc/hash.h @@ -1,215 +1,3 @@ -/* Hash tables for Objective C method dispatch. - Copyright (C) 1993, 1995, 1996, 2004, 2009 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 3, 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. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - - - -#ifndef __hash_INCLUDE_GNU -#define __hash_INCLUDE_GNU - -#include <stddef.h> -#include <string.h> #include "objc.h" +#include "deprecated/hash.h" -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* - * This data structure is used to hold items - * stored in a hash table. Each node holds - * a key/value pair. - * - * Items in the cache are really of type void *. - */ -typedef struct cache_node -{ - struct cache_node *next; /* Pointer to next entry on the list. - NULL indicates end of list. */ - const void *key; /* Key used to locate the value. Used - to locate value when more than one - key computes the same hash - value. */ - void *value; /* Value stored for the key. */ -} *node_ptr; - - -/* - * This data type is the function that computes a hash code given a key. - * Therefore, the key can be a pointer to anything and the function specific - * to the key type. - * - * Unfortunately there is a mutual data structure reference problem with this - * typedef. Therefore, to remove compiler warnings the functions passed to - * objc_hash_new will have to be casted to this type. - */ -typedef unsigned int (*hash_func_type) (void *, const void *); - -/* - * This data type is the function that compares two hash keys and returns an - * integer greater than, equal to, or less than 0, according as the first - * parameter is lexicographically greater than, equal to, or less than the - * second. - */ - -typedef int (*compare_func_type) (const void *, const void *); - - -/* - * This data structure is the cache. - * - * It must be passed to all of the hashing routines - * (except for new). - */ -typedef struct cache -{ - /* Variables used to implement the hash itself. */ - node_ptr *node_table; /* Pointer to an array of hash nodes. */ - /* Variables used to track the size of the hash table so to determine - when to resize it. */ - unsigned int size; /* Number of buckets allocated for the hash table - (number of array entries allocated for - "node_table"). Must be a power of two. */ - unsigned int used; /* Current number of entries in the hash table. */ - unsigned int mask; /* Precomputed mask. */ - - /* Variables used to implement indexing through the hash table. */ - - unsigned int last_bucket; /* Tracks which entry in the array where - the last value was returned. */ - /* Function used to compute a hash code given a key. - This function is specified when the hash table is created. */ - hash_func_type hash_func; - /* Function used to compare two hash keys to see if they are equal. */ - compare_func_type compare_func; -} *cache_ptr; - - -/* Two important hash tables. */ -extern cache_ptr module_hash_table, class_hash_table; - -/* Allocate and initialize a hash table. */ - -cache_ptr objc_hash_new (unsigned int size, - hash_func_type hash_func, - compare_func_type compare_func); - -/* Deallocate all of the hash nodes and the cache itself. */ - -void objc_hash_delete (cache_ptr cache); - -/* Add the key/value pair to the hash table. If the - hash table reaches a level of fullness then it will be resized. - - assert if the key is already in the hash. */ - -void objc_hash_add (cache_ptr *cachep, const void *key, void *value); - -/* Remove the key/value pair from the hash table. - assert if the key isn't in the table. */ - -void objc_hash_remove (cache_ptr cache, const void *key); - -/* Used to index through the hash table. Start with NULL - to get the first entry. - - Successive calls pass the value returned previously. - ** Don't modify the hash during this operation *** - - Cache nodes are returned such that key or value can - be extracted. */ - -node_ptr objc_hash_next (cache_ptr cache, node_ptr node); - -/* Used to return a value from a hash table using a given key. */ - -void *objc_hash_value_for_key (cache_ptr cache, const void *key); - -/* Used to determine if the given key exists in the hash table */ - -BOOL objc_hash_is_key_in_hash (cache_ptr cache, const void *key); - -/************************************************ - - Useful hashing functions. - - Declared inline for your pleasure. - -************************************************/ - -/* Calculate a hash code by performing some - manipulation of the key pointer. (Use the lowest bits - except for those likely to be 0 due to alignment.) */ - -static inline unsigned int -objc_hash_ptr (cache_ptr cache, const void *key) -{ - return ((size_t)key / sizeof (void *)) & cache->mask; -} - - -/* Calculate a hash code by iterating over a NULL - terminate string. */ -static inline unsigned int -objc_hash_string (cache_ptr cache, const void *key) -{ - unsigned int ret = 0; - unsigned int ctr = 0; - const char *ckey = (const char *) key; - - while (*ckey) { - ret ^= *ckey++ << ctr; - ctr = (ctr + 1) % sizeof (void *); - } - - return ret & cache->mask; -} - - -/* Compare two pointers for equality. */ -static inline int -objc_compare_ptrs (const void *k1, const void *k2) -{ - return (k1 == k2); -} - - -/* Compare two strings. */ -static inline int -objc_compare_strings (const void *k1, const void *k2) -{ - if (k1 == k2) - return 1; - else if (k1 == 0 || k2 == 0) - return 0; - else - return ! strcmp ((const char *) k1, (const char *) k2); -} - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif /* not __hash_INCLUDE_GNU */ diff --git a/libobjc/objc/message.h b/libobjc/objc/message.h index 31ee33b305c..6d476363c69 100644 --- a/libobjc/objc/message.h +++ b/libobjc/objc/message.h @@ -31,6 +31,7 @@ extern "C" { #endif #include "objc.h" +#include "objc-decls.h" /* This file includes declarations of the messaging functions and types. */ @@ -41,7 +42,7 @@ typedef union arglist { char arg_regs[sizeof (char*)]; } *arglist_t; /* argument frame */ -IMP objc_msg_lookup(id receiver, SEL op); +objc_EXPORT IMP objc_msg_lookup(id receiver, SEL op); /* TODO: Add the remaining messaging declarations from objc-api.h. */ diff --git a/libobjc/objc/objc-api.h b/libobjc/objc/objc-api.h index 9fff9e1d155..9903739248c 100644 --- a/libobjc/objc/objc-api.h +++ b/libobjc/objc/objc-api.h @@ -28,7 +28,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define __objc_api_INCLUDE_GNU #include "objc.h" -#include "hash.h" +#ifndef GNU_LIBOBJC_COMPILING_LIBOBJC_ITSELF +# include "deprecated/hash.h" +#endif #include "thr.h" #include "objc-decls.h" #include <stdio.h> @@ -296,9 +298,9 @@ typedef struct objc_super { #endif } Super, *Super_t; -IMP objc_msg_lookup_super(Super_t super, SEL sel); +objc_EXPORT IMP objc_msg_lookup_super(Super_t super, SEL sel); -retval_t objc_msg_sendv(id, SEL, arglist_t); +objc_EXPORT retval_t objc_msg_sendv(id, SEL, arglist_t); @@ -330,22 +332,22 @@ objc_EXPORT id (*_objc_object_dispose)(id object); use these functions in their ObjC programs so that they work so that they work properly with garbage collectors. */ -void * +objc_EXPORT void * objc_malloc(size_t size); /* FIXME: Shouldn't the following be called objc_malloc_atomic ? The GC function is GC_malloc_atomic() which makes sense. */ -void * +objc_EXPORT void * objc_atomic_malloc(size_t size); -void * +objc_EXPORT void * objc_realloc(void *mem, size_t size); -void * +objc_EXPORT void * objc_calloc(size_t nelem, size_t size); -void +objc_EXPORT void objc_free(void *mem); #include "deprecated/objc_valloc.h" @@ -363,36 +365,36 @@ objc_EXPORT IMP (*__objc_msg_forward2)(id, SEL); #include "deprecated/objc_unexpected_exception.h" -Method_t class_get_class_method(MetaClass _class, SEL aSel); +objc_EXPORT Method_t class_get_class_method(MetaClass _class, SEL aSel); -Method_t class_get_instance_method(Class _class, SEL aSel); +objc_EXPORT Method_t class_get_instance_method(Class _class, SEL aSel); -Class class_pose_as(Class impostor, Class superclass); +objc_EXPORT Class class_pose_as(Class impostor, Class superclass); -Class objc_get_class(const char *name); +objc_EXPORT Class objc_get_class(const char *name); -Class objc_lookup_class(const char *name); +objc_EXPORT Class objc_lookup_class(const char *name); -Class objc_next_class(void **enum_state); +objc_EXPORT Class objc_next_class(void **enum_state); -const char *sel_get_name(SEL selector); +objc_EXPORT const char *sel_get_name(SEL selector); -const char *sel_get_type(SEL selector); +objc_EXPORT const char *sel_get_type(SEL selector); -SEL sel_get_uid(const char *name); +objc_EXPORT SEL sel_get_uid(const char *name); -SEL sel_get_any_uid(const char *name); +objc_EXPORT SEL sel_get_any_uid(const char *name); -SEL sel_get_any_typed_uid(const char *name); +objc_EXPORT SEL sel_get_any_typed_uid(const char *name); -SEL sel_get_typed_uid(const char *name, const char*); +objc_EXPORT SEL sel_get_typed_uid(const char *name, const char*); -SEL sel_register_name(const char *name); +objc_EXPORT SEL sel_register_name(const char *name); -SEL sel_register_typed_name(const char *name, const char*type); +objc_EXPORT SEL sel_register_typed_name(const char *name, const char*type); -BOOL sel_is_mapped (SEL aSel); +objc_EXPORT BOOL sel_is_mapped (SEL aSel); extern id class_create_instance(Class _class); @@ -463,11 +465,11 @@ method_get_imp(Method_t method) return (method!=METHOD_NULL)?method->method_imp:(IMP)0; } -IMP get_imp (Class _class, SEL sel); +objc_EXPORT IMP get_imp (Class _class, SEL sel); -id object_copy(id object); +objc_EXPORT id object_copy(id object); -id object_dispose(id object); +objc_EXPORT id object_dispose(id object); static inline Class object_get_class(id object) @@ -533,7 +535,7 @@ object_is_meta_class (id object) && !object_is_class (object)); } -struct sarray* +objc_EXPORT struct sarray* objc_get_uninstalled_dtable(void); #ifdef __cplusplus diff --git a/libobjc/objc/objc-decls.h b/libobjc/objc/objc-decls.h index 6054237afb9..e5388e33c4c 100644 --- a/libobjc/objc/objc-decls.h +++ b/libobjc/objc/objc-decls.h @@ -29,8 +29,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #if defined (_WIN32) || defined (__WIN32__) || defined (WIN32) # ifdef DLL_EXPORT /* defined by libtool (if required) */ -# define objc_EXPORT __declspec(dllexport) -# define objc_DECLARE __declspec(dllexport) +# define objc_EXPORT +# define objc_DECLARE #else # define objc_EXPORT extern __declspec(dllimport) # define objc_DECLARE extern __declspec(dllimport) diff --git a/libobjc/objc/objc-list.h b/libobjc/objc/objc-list.h index e542bfc0498..b713a3c0ec9 100644 --- a/libobjc/objc/objc-list.h +++ b/libobjc/objc/objc-list.h @@ -1,155 +1,2 @@ -/* Generic single linked list to keep various information - Copyright (C) 1993, 1994, 1996, 2009 Free Software Foundation, Inc. - Contributed by Kresten Krab Thorup. +#include "deprecated/objc-list.h" -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 3, 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. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - - -#ifndef __GNU_OBJC_LIST_H -#define __GNU_OBJC_LIST_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -struct objc_list { - void *head; - struct objc_list *tail; -}; - -/* Return a cons cell produced from (head . tail) */ - -static inline struct objc_list* -list_cons(void* head, struct objc_list* tail) -{ - struct objc_list* cell; - - cell = (struct objc_list*)objc_malloc(sizeof(struct objc_list)); - cell->head = head; - cell->tail = tail; - return cell; -} - -/* Return the length of a list, list_length(NULL) returns zero */ - -static inline int -list_length(struct objc_list* list) -{ - int i = 0; - while(list) - { - i += 1; - list = list->tail; - } - return i; -} - -/* Return the Nth element of LIST, where N count from zero. If N - larger than the list length, NULL is returned */ - -static inline void* -list_nth(int indx, struct objc_list* list) -{ - while(indx-- != 0) - { - if(list->tail) - list = list->tail; - else - return 0; - } - return list->head; -} - -/* Remove the element at the head by replacing it by its successor */ - -static inline void -list_remove_head(struct objc_list** list) -{ - if ((*list)->tail) - { - struct objc_list* tail = (*list)->tail; /* fetch next */ - *(*list) = *tail; /* copy next to list head */ - objc_free(tail); /* free next */ - } - else /* only one element in list */ - { - objc_free(*list); - (*list) = 0; - } -} - - -/* Remove the element with `car' set to ELEMENT */ - -static inline void -list_remove_elem(struct objc_list** list, void* elem) -{ - while (*list) { - if ((*list)->head == elem) - list_remove_head(list); - list = &((*list)->tail); - } -} - -/* Map FUNCTION over all elements in LIST */ - -static inline void -list_mapcar(struct objc_list* list, void(*function)(void*)) -{ - while(list) - { - (*function)(list->head); - list = list->tail; - } -} - -/* Return element that has ELEM as car */ - -static inline struct objc_list** -list_find(struct objc_list** list, void* elem) -{ - while(*list) - { - if ((*list)->head == elem) - return list; - list = &((*list)->tail); - } - return NULL; -} - -/* Free list (backwards recursive) */ - -static inline void -list_free(struct objc_list* list) -{ - if(list) - { - list_free(list->tail); - objc_free(list); - } -} - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* not __GNU_OBJC_LIST_H */ diff --git a/libobjc/objc/sarray.h b/libobjc/objc/sarray.h index 32a7ef2aa43..ff51e47f918 100644 --- a/libobjc/objc/sarray.h +++ b/libobjc/objc/sarray.h @@ -1,243 +1,2 @@ -/* Sparse Arrays for Objective C dispatch tables - Copyright (C) 1993, 1995, 1996, 2004, 2009 Free Software Foundation, Inc. - Contributed by Kresten Krab Thorup. +#include "deprecated/sarray.h" -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 3, 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. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - - -#ifndef __sarray_INCLUDE_GNU -#define __sarray_INCLUDE_GNU - -#include "thr.h" - -#define OBJC_SPARSE2 /* 2-level sparse array */ -/* #define OBJC_SPARSE3 */ /* 3-level sparse array */ - -#ifdef OBJC_SPARSE2 -extern const char* __objc_sparse2_id; -#endif - -#ifdef OBJC_SPARSE3 -extern const char* __objc_sparse3_id; -#endif - -#include <stddef.h> -#include <assert.h> - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -extern int nbuckets; /* for stats */ -extern int nindices; -extern int narrays; -extern int idxsize; - -/* An unsigned integer of same size as a pointer */ -#define SIZET_BITS (sizeof(size_t)*8) - -#if defined(__sparc__) || defined(OBJC_SPARSE2) -#define PRECOMPUTE_SELECTORS -#endif - -#ifdef OBJC_SPARSE3 - -/* Buckets are 8 words each */ -#define BUCKET_BITS 3 -#define BUCKET_SIZE (1<<BUCKET_BITS) -#define BUCKET_MASK (BUCKET_SIZE-1) - -/* Indices are 16 words each */ -#define INDEX_BITS 4 -#define INDEX_SIZE (1<<INDEX_BITS) -#define INDEX_MASK (INDEX_SIZE-1) - -#define INDEX_CAPACITY (BUCKET_SIZE*INDEX_SIZE) - -#else /* OBJC_SPARSE2 */ - -/* Buckets are 32 words each */ -#define BUCKET_BITS 5 -#define BUCKET_SIZE (1<<BUCKET_BITS) -#define BUCKET_MASK (BUCKET_SIZE-1) - -#endif /* OBJC_SPARSE2 */ - -typedef size_t sidx; - -#ifdef PRECOMPUTE_SELECTORS - -struct soffset { -#ifdef OBJC_SPARSE3 - unsigned int unused : SIZET_BITS/4; - unsigned int eoffset : SIZET_BITS/4; - unsigned int boffset : SIZET_BITS/4; - unsigned int ioffset : SIZET_BITS/4; -#else /* OBJC_SPARSE2 */ -#ifdef __sparc__ - unsigned long boffset : (SIZET_BITS - 2) - BUCKET_BITS; - unsigned int eoffset : BUCKET_BITS; - unsigned int unused : 2; -#else - unsigned int boffset : SIZET_BITS/2; - unsigned int eoffset : SIZET_BITS/2; -#endif -#endif /* OBJC_SPARSE2 */ -}; - -union sofftype { - struct soffset off; - sidx idx; -}; - -#endif /* not PRECOMPUTE_SELECTORS */ - -union sversion { - int version; - void *next_free; -}; - -struct sbucket { - void* elems[BUCKET_SIZE]; /* elements stored in array */ - union sversion version; /* used for copy-on-write */ -}; - -#ifdef OBJC_SPARSE3 - -struct sindex { - struct sbucket* buckets[INDEX_SIZE]; - union sversion version; /* used for copy-on-write */ -}; - -#endif /* OBJC_SPARSE3 */ - -struct sarray { -#ifdef OBJC_SPARSE3 - struct sindex** indices; - struct sindex* empty_index; -#else /* OBJC_SPARSE2 */ - struct sbucket** buckets; -#endif /* OBJC_SPARSE2 */ - struct sbucket* empty_bucket; - union sversion version; /* used for copy-on-write */ - short ref_count; - struct sarray* is_copy_of; - size_t capacity; -}; - -struct sarray* sarray_new(int, void* default_element); -void sarray_free(struct sarray*); -struct sarray* sarray_lazy_copy(struct sarray*); -void sarray_realloc(struct sarray*, int new_size); -void sarray_at_put(struct sarray*, sidx indx, void* elem); -void sarray_at_put_safe(struct sarray*, sidx indx, void* elem); - -struct sarray* sarray_hard_copy(struct sarray*); /* ... like the name? */ -void sarray_remove_garbage(void); - - -#ifdef PRECOMPUTE_SELECTORS -/* Transform soffset values to ints and vica verca */ -static inline unsigned int -soffset_decode(sidx indx) -{ - union sofftype x; - x.idx = indx; -#ifdef OBJC_SPARSE3 - return x.off.eoffset - + (x.off.boffset*BUCKET_SIZE) - + (x.off.ioffset*INDEX_CAPACITY); -#else /* OBJC_SPARSE2 */ - return x.off.eoffset + (x.off.boffset*BUCKET_SIZE); -#endif /* OBJC_SPARSE2 */ -} - -static inline sidx -soffset_encode(size_t offset) -{ - union sofftype x; - x.off.eoffset = offset%BUCKET_SIZE; -#ifdef OBJC_SPARSE3 - x.off.boffset = (offset/BUCKET_SIZE)%INDEX_SIZE; - x.off.ioffset = offset/INDEX_CAPACITY; -#else /* OBJC_SPARSE2 */ - x.off.boffset = offset/BUCKET_SIZE; -#endif - return (sidx)x.idx; -} - -#else /* not PRECOMPUTE_SELECTORS */ - -static inline size_t -soffset_decode(sidx indx) -{ - return indx; -} - -static inline sidx -soffset_encode(size_t offset) -{ - return offset; -} -#endif /* not PRECOMPUTE_SELECTORS */ - -/* Get element from the Sparse array `array' at offset `indx' */ - -static inline void* sarray_get(struct sarray* array, sidx indx) -{ -#ifdef PRECOMPUTE_SELECTORS - union sofftype x; - x.idx = indx; -#ifdef OBJC_SPARSE3 - return - array-> - indices[x.off.ioffset]-> - buckets[x.off.boffset]-> - elems[x.off.eoffset]; -#else /* OBJC_SPARSE2 */ - return array->buckets[x.off.boffset]->elems[x.off.eoffset]; -#endif /* OBJC_SPARSE2 */ -#else /* not PRECOMPUTE_SELECTORS */ -#ifdef OBJC_SPARSE3 - return array-> - indices[indx/INDEX_CAPACITY]-> - buckets[(indx/BUCKET_SIZE)%INDEX_SIZE]-> - elems[indx%BUCKET_SIZE]; -#else /* OBJC_SPARSE2 */ - return array->buckets[indx/BUCKET_SIZE]->elems[indx%BUCKET_SIZE]; -#endif /* not OBJC_SPARSE3 */ -#endif /* not PRECOMPUTE_SELECTORS */ -} - -static inline void* sarray_get_safe(struct sarray* array, sidx indx) -{ - if(soffset_decode(indx) < array->capacity) - return sarray_get(array, indx); - else - return (array->empty_bucket->elems[0]); -} - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __sarray_INCLUDE_GNU */ diff --git a/libobjc/objc/typedstream.h b/libobjc/objc/typedstream.h index 2d4f72d5965..a39c51b29dc 100644 --- a/libobjc/objc/typedstream.h +++ b/libobjc/objc/typedstream.h @@ -1,4 +1,4 @@ #include "objc.h" -#include "hash.h" +#include "deprecated/hash.h" #include "deprecated/typedstream.h" diff --git a/libobjc/objects.c b/libobjc/objects.c index 0743af427a0..9c237f49ea5 100644 --- a/libobjc/objects.c +++ b/libobjc/objects.c @@ -23,6 +23,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ #include "objc-private/common.h" +#include <string.h> /* For memset */ #include "tconfig.h" /* include defs of bzero for target */ #include "objc/objc.h" #include "objc/objc-api.h" diff --git a/libobjc/sarray.c b/libobjc/sarray.c index dd140c76f36..8d5303701e0 100644 --- a/libobjc/sarray.c +++ b/libobjc/sarray.c @@ -23,13 +23,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ #include "objc-private/common.h" -#include "objc/sarray.h" +#include "objc-private/sarray.h" #include "objc/objc.h" #include "objc/objc-api.h" #include "objc/thr.h" #include "objc-private/runtime.h" #include <stdio.h> -#include "assert.h" +#include <string.h> /* For memset */ +#include <assert.h> /* For assert */ int nbuckets = 0; /* !T:MUTEX */ int nindices = 0; /* !T:MUTEX */ diff --git a/libobjc/selector.c b/libobjc/selector.c index 52b6ba12da5..10b7ab63dad 100644 --- a/libobjc/selector.c +++ b/libobjc/selector.c @@ -26,10 +26,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc/objc.h" #include "objc/objc-api.h" #include "objc/thr.h" -#include "objc/hash.h" -#include "objc/objc-list.h" +#include "objc-private/hash.h" +#include "objc-private/objc-list.h" #include "objc-private/runtime.h" -#include "objc/sarray.h" +#include "objc-private/sarray.h" #include "objc/encoding.h" /* Initial selector hash table size. Value doesn't matter much */ diff --git a/libobjc/sendmsg.c b/libobjc/sendmsg.c index 32d9dc7bea6..621d5314d37 100644 --- a/libobjc/sendmsg.c +++ b/libobjc/sendmsg.c @@ -37,9 +37,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "objc/objc-api.h" #include "objc/thr.h" #include "objc-private/runtime.h" -#include "objc/sarray.h" +#include "objc-private/sarray.h" #include "objc/encoding.h" #include "runtime-info.h" +#include <assert.h> /* For assert */ +#include <string.h> /* For strlen */ /* This is how we hack STRUCT_VALUE to be 1 or 0. */ #define gen_rtx(args...) 1 @@ -220,7 +222,7 @@ __objc_responds_to (id object, SEL sel) /* This is the lookup function. All entries in the table are either a valid method *or* zero. If zero then either the dispatch table needs to be installed or it doesn't exist and forwarding is attempted. */ -inline + IMP objc_msg_lookup (id receiver, SEL op) { @@ -711,7 +713,7 @@ __objc_print_dtable_stats () /* Returns the uninstalled dispatch table indicator. If a class' dispatch table points to __objc_uninstalled_dtable then that means it needs its dispatch table to be installed. */ -inline + struct sarray * objc_get_uninstalled_dtable () { diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index aa9d6249248..42ea0b3d326 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,114 @@ +2010-09-27 Paolo Carlini <paolo.carlini@oracle.com> + + * include/c_std/cmath (__pow_helper): Remove. + (__cmath_power): Remove declaration. + * include/c_global/cmath: Likewise. + * include/std/complex (__complex_pow_unsigned): Add. + (pow(const complex<_Tp>&, int)): Use the latter. + * include/c_std/cmath.tcc: Remove file. + * include/c_global/cmath.tcc: Likewise. + * acinclude.m4: Adjust. + * include/Makefile.am: Likewise. + * configure: Regenerate. + * include/Makefile.in: Likewise. + +2010-09-22 David Krauss <potswa@mac.com> + + PR libstdc++/45628 + * include/bits/fstream.tcc (basic_filebuf::underflow): Add state + transition to avoid modality requiring seekoff(0,ios::cur). + (basic_filebuf::pbackfail): Likewise. + (basic_filebuf::overflow): Likewise. + (basic_filebuf::_M_seek): Avoid minor unnecessary conversion. + (basic_filebuf::seekoff): Remove code to _M_get_ext_pos; make + (0, ios::cur) a special case preserving buffer contents. + (basic_filebuf::_M_get_ext_pos): New function to obtain status + about codecvt extern_t buffer for overflow and seekoff. + * include/std/fstream (basic_filebuf::_M_get_ext_pos): Likewise. + * config/abi/pre/gnu.ver: Export new symbols. + * testsuite/27_io/basic_filebuf/seekoff/char/45628-1.cc: New, + verifies that seekoff(0, ios::cur) preserves buffers. + * testsuite/27_io/basic_filebuf/seekoff/45628-2.cc: Likewise. + for codecvt case. More lenient as it may still flush put area. + * testsuite/27_io/basic_filebuf/seekoff/char/4.cc: Modify to + check that seekoff is not required between read and write. + * testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc: Likewise. + * testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc: Remove. + * testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc: Likewise. + * testsuite/util/testsuite_character.h (codecvt::do_length): Comply + with 22.2.1.5.2/10 "Returns ... the LARGEST value in the range..." + +2010-09-22 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/functional_hash.h (__hash_base): Add. + (hash): Derive from __hash_base instead. + * include/debug/bitset (hash): Likewise. + * include/debug/vector (hash): Likewise. + * include/std/system_error (hash): Likewise. + * include/std/thread (hash): Likewise. + * include/std/bitset (hash): Likewise. + * include/profile/bitset (hash): Likewise. + * include/profile/vector (hash): Likewise. + * include/bits/basic_string.h (hash): Likewise. + * include/bits/stl_bvector.h (hash): Likewise. + * include/std/typeindex (hash): Do not derive from unary_function, + add result_type and argument_type typedefs; trim includes. + +2010-09-22 Paolo Carlini <paolo.carlini@oracle.com> + + * include/std/typeindex: New. + * include/Makefile.am: Add. + * include/Makefile.in: Regenerate. + * include/precompiled/stdc++.h: Add. + * testsuite/20_util/typeindex/comparison_operators.cc: New. + * testsuite/20_util/typeindex/hash.cc: Likewise. + * testsuite/20_util/typeindex/hash_code.cc: Likewise. + * testsuite/20_util/typeindex/name.cc: Likewise. + + * testsuite/18_support/type_info/hash_code.cc: Tweak. + +2010-09-22 Paolo Carlini <paolo.carlini@oracle.com> + + * src/hash_bytes.cc: Move... + * libsupc++/hash_bytes.cc: ... here. + * src/Makefile.am: Adjust. + * libsupc++/Makefile.am: Likewise. + * config/abi/pre/gnu.ver: Likewise. + * libsupc++/typeinfo (type_info::hash_code): Add in C++0x mode. + * src/Makefile.in: Regenerate. + * libsupc++/Makefile.am: Likewise. + * testsuite/18_support/type_info/hash_code.cc: New. + +2010-09-20 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + PR libstdc++/45711 + * src/Makefile.am (stamp-debug): Also adjust possibly-relative + file names in MKDIR_P, and, for consistency, also top_build_prefix. + * src/Makefile.in: Regenerate. + +2010-09-19 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * include/ext/throw_allocator.h + (hash<__gnu_cxx::throw_value_limit>::operator()): Uglify local. + (hash<__gnu_cxx::throw_value_random>::operator()): Likewise. + * include/parallel/set_operations.h (__symmetric_difference_func): + Uglify remaining arguments to __count, __first_empty, _M_invoke. + (__difference_func): Likewise for __count. + * include/profile/impl/profiler_node.h + (__object_info_base::__write): Uglify parameter. + +2010-09-19 Paolo Carlini <paolo.carlini@oracle.com> + + * src/hash_bytes.cc: Compile load_bytes and shift_mix only when + __SIZEOF_SIZE_T__ == 8. + +2010-09-17 Luc Hermitte <hermitte@free.fr> + Paolo Carlini <paolo.carlini@oracle.com> + + PR libstdc++/45713 + * include/std/bitset: Fix _GLIBCXX_BITSET_WORDS macro. + * testsuite/23_containers/bitset/45713.cc: New. + 2010-09-16 Paolo Carlini <paolo.carlini@oracle.com> * include/bits/stl_raw_storage_iter.h (raw_storage_iterator<>:: diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index 5c856baab8d..3b14f02dd3b 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -1695,16 +1695,11 @@ AC_DEFUN([GLIBCXX_ENABLE_CHEADERS], [ c_compatibility=yes fi - if test $enable_cheaders = c_global || test $enable_cheaders = c_std; then - c_extra=yes - fi - AC_SUBST(C_INCLUDE_DIR) GLIBCXX_CONDITIONAL(GLIBCXX_C_HEADERS_C, test $enable_cheaders = c) GLIBCXX_CONDITIONAL(GLIBCXX_C_HEADERS_C_STD, test $enable_cheaders = c_std) GLIBCXX_CONDITIONAL(GLIBCXX_C_HEADERS_C_GLOBAL, test $enable_cheaders = c_global) GLIBCXX_CONDITIONAL(GLIBCXX_C_HEADERS_COMPATIBILITY, test $c_compatibility = yes) - GLIBCXX_CONDITIONAL(GLIBCXX_C_HEADERS_EXTRA, test $c_extra = yes) ]) diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index aff2593425e..4981ca90740 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -332,7 +332,13 @@ GLIBCXX_3.4 { # std::basic_filebuf _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EEC*; _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EED*; - _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE[0-3]*; + _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE0*; + _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE13*; + _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE15*; + _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE16*; + _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE19*; + _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE2*; + _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE3*; _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE4openEPKc*; _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE4sync*; _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE[5-9]*; @@ -1178,11 +1184,8 @@ GLIBCXX_3.4.15 { _ZNSbIwSt11char_traitsIwESaIwEE4backEv; _ZNKSbIwSt11char_traitsIwESaIwEE4backEv; - # Default function. - _ZSt11_Hash_bytesPKv*; - - # FNV hash. - _ZSt15_Fnv_hash_bytesPKv*; + # basic_filebuf::_M_get_ext_pos + _ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE14_M_get_ext_pos*; } GLIBCXX_3.4.14; @@ -1356,4 +1359,10 @@ CXXABI_1.3.5 { _ZTIPDn; _ZTIPKDn; + # Default function. + _ZSt11_Hash_bytesPKv*; + + # FNV hash. + _ZSt15_Fnv_hash_bytesPKv*; + } CXXABI_1.3.4; diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 0032823bcfd..166d2e3021a 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -649,8 +649,6 @@ ENABLE_PARALLEL_TRUE GLIBCXX_BUILD_DEBUG_FALSE GLIBCXX_BUILD_DEBUG_TRUE DEBUG_FLAGS -GLIBCXX_C_HEADERS_EXTRA_FALSE -GLIBCXX_C_HEADERS_EXTRA_TRUE GLIBCXX_C_HEADERS_COMPATIBILITY_FALSE GLIBCXX_C_HEADERS_COMPATIBILITY_TRUE GLIBCXX_C_HEADERS_C_GLOBAL_FALSE @@ -11468,7 +11466,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11471 "configure" +#line 11469 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11574,7 +11572,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11577 "configure" +#line 11575 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14914,7 +14912,7 @@ fi # # Fake what AC_TRY_COMPILE does. XXX Look at redoing this new-style. cat > conftest.$ac_ext << EOF -#line 14917 "configure" +#line 14915 "configure" struct S { ~S(); }; void bar(); void foo() @@ -15282,7 +15280,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; } # Fake what AC_TRY_COMPILE does. cat > conftest.$ac_ext << EOF -#line 15285 "configure" +#line 15283 "configure" int main() { typedef bool atomic_type; @@ -15319,7 +15317,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15322 "configure" +#line 15320 "configure" int main() { typedef short atomic_type; @@ -15356,7 +15354,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15359 "configure" +#line 15357 "configure" int main() { // NB: _Atomic_word not necessarily int. @@ -15394,7 +15392,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15397 "configure" +#line 15395 "configure" int main() { typedef long long atomic_type; @@ -15470,7 +15468,7 @@ $as_echo "$as_me: WARNING: Performance of certain classes will degrade as a resu # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 15473 "configure" +#line 15471 "configure" int main() { _Decimal32 d1; @@ -16071,11 +16069,6 @@ $as_echo "$as_me: \"C\" header strategy set to $enable_cheaders" >&6;} c_compatibility=yes fi - if test $enable_cheaders = c_global || test $enable_cheaders = c_std; then - c_extra=yes - fi - - @@ -58987,15 +58980,6 @@ else fi - if test $c_extra = yes; then - GLIBCXX_C_HEADERS_EXTRA_TRUE= - GLIBCXX_C_HEADERS_EXTRA_FALSE='#' -else - GLIBCXX_C_HEADERS_EXTRA_TRUE='#' - GLIBCXX_C_HEADERS_EXTRA_FALSE= -fi - - if test $enable_libstdcxx_debug = yes; then GLIBCXX_BUILD_DEBUG_TRUE= GLIBCXX_BUILD_DEBUG_FALSE='#' @@ -59453,10 +59437,6 @@ if test -z "${GLIBCXX_C_HEADERS_COMPATIBILITY_TRUE}" && test -z "${GLIBCXX_C_HEA as_fn_error "conditional \"GLIBCXX_C_HEADERS_COMPATIBILITY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${GLIBCXX_C_HEADERS_EXTRA_TRUE}" && test -z "${GLIBCXX_C_HEADERS_EXTRA_FALSE}"; then - as_fn_error "conditional \"GLIBCXX_C_HEADERS_EXTRA\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${GLIBCXX_BUILD_DEBUG_TRUE}" && test -z "${GLIBCXX_BUILD_DEBUG_FALSE}"; then as_fn_error "conditional \"GLIBCXX_BUILD_DEBUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 3b9c5519d4a..460e1ffa3a7 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -66,6 +66,7 @@ std_headers = \ ${std_srcdir}/system_error \ ${std_srcdir}/thread \ ${std_srcdir}/tuple \ + ${std_srcdir}/typeindex \ ${std_srcdir}/type_traits \ ${std_srcdir}/unordered_map \ ${std_srcdir}/unordered_set \ @@ -823,15 +824,8 @@ profile_impl_headers = \ ${profile_impl_srcdir}/profiler_list_to_vector.h \ ${profile_impl_srcdir}/profiler_list_to_slist.h -# Some of the different "C" header models need extra files. # Some "C" header schemes require the "C" compatibility headers. # For --enable-cheaders=c_std -if GLIBCXX_C_HEADERS_EXTRA -c_base_headers_extra = ${c_base_srcdir}/cmath.tcc -else -c_base_headers_extra = -endif - if GLIBCXX_C_HEADERS_COMPATIBILITY c_compatibility_headers_extra = ${c_compatibility_headers} else @@ -914,10 +908,10 @@ endif # List of all timestamp files. By keeping only one copy of this list, both # CLEANFILES and all-local are kept up-to-date. allstamped = \ - stamp-std stamp-bits stamp-c_base stamp-c_base_extra \ - stamp-c_compatibility stamp-backward stamp-ext stamp-pb \ - stamp-tr1 stamp-tr1-impl stamp-decimal stamp-debug \ - stamp-parallel stamp-profile stamp-profile-impl stamp-host + stamp-std stamp-bits stamp-c_base stamp-c_compatibility \ + stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr1-impl \ + stamp-decimal stamp-debug stamp-parallel stamp-profile \ + stamp-profile-impl stamp-host # List of all files that are created by explicit building, editing, or # catenation. diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index d32efa8e7fd..f8a971865bc 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -308,6 +308,7 @@ std_headers = \ ${std_srcdir}/system_error \ ${std_srcdir}/thread \ ${std_srcdir}/tuple \ + ${std_srcdir}/typeindex \ ${std_srcdir}/type_traits \ ${std_srcdir}/unordered_map \ ${std_srcdir}/unordered_set \ @@ -1057,13 +1058,10 @@ profile_impl_headers = \ ${profile_impl_srcdir}/profiler_list_to_vector.h \ ${profile_impl_srcdir}/profiler_list_to_slist.h -@GLIBCXX_C_HEADERS_EXTRA_FALSE@c_base_headers_extra = +@GLIBCXX_C_HEADERS_COMPATIBILITY_FALSE@c_compatibility_headers_extra = -# Some of the different "C" header models need extra files. # Some "C" header schemes require the "C" compatibility headers. # For --enable-cheaders=c_std -@GLIBCXX_C_HEADERS_EXTRA_TRUE@c_base_headers_extra = ${c_base_srcdir}/cmath.tcc -@GLIBCXX_C_HEADERS_COMPATIBILITY_FALSE@c_compatibility_headers_extra = @GLIBCXX_C_HEADERS_COMPATIBILITY_TRUE@c_compatibility_headers_extra = ${c_compatibility_headers} host_srcdir = ${glibcxx_srcdir}/$(OS_INC_SRCDIR) host_builddir = ./${host_alias}/bits @@ -1137,10 +1135,10 @@ PCHFLAGS = -x c++-header -nostdinc++ $(CXXFLAGS) # List of all timestamp files. By keeping only one copy of this list, both # CLEANFILES and all-local are kept up-to-date. allstamped = \ - stamp-std stamp-bits stamp-c_base stamp-c_base_extra \ - stamp-c_compatibility stamp-backward stamp-ext stamp-pb \ - stamp-tr1 stamp-tr1-impl stamp-decimal stamp-debug \ - stamp-parallel stamp-profile stamp-profile-impl stamp-host + stamp-std stamp-bits stamp-c_base stamp-c_compatibility \ + stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr1-impl \ + stamp-decimal stamp-debug stamp-parallel stamp-profile \ + stamp-profile-impl stamp-host # List of all files that are created by explicit building, editing, or diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 2fb671721ab..308285bec86 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -2925,7 +2925,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) /// std::hash specialization for string. template<> struct hash<string> - : public std::unary_function<string, size_t> + : public __hash_base<size_t, string> { size_t operator()(const string& __s) const @@ -2936,7 +2936,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) /// std::hash specialization for wstring. template<> struct hash<wstring> - : public std::unary_function<wstring, size_t> + : public __hash_base<size_t, wstring> { size_t operator()(const wstring& __s) const @@ -2950,7 +2950,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) /// std::hash specialization for u16string. template<> struct hash<u16string> - : public std::unary_function<u16string, size_t> + : public __hash_base<size_t, u16string> { size_t operator()(const u16string& __s) const @@ -2961,7 +2961,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) /// std::hash specialization for u32string. template<> struct hash<u32string> - : public std::unary_function<u32string, size_t> + : public __hash_base<size_t, u32string> { size_t operator()(const u32string& __s) const diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc index c498f48caee..2f661ebd23e 100644 --- a/libstdc++-v3/include/bits/fstream.tcc +++ b/libstdc++-v3/include/bits/fstream.tcc @@ -1,7 +1,7 @@ // File based streams -*- C++ -*- // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, -// 2007, 2008, 2009 +// 2007, 2008, 2009, 2010 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -205,8 +205,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { int_type __ret = traits_type::eof(); const bool __testin = _M_mode & ios_base::in; - if (__testin && !_M_writing) + if (__testin) { + if (_M_writing) + { + __ret = overflow(); + if (__ret == traits_type::eof()) + return __ret; + _M_set_buffer(-1); + _M_writing = false; + } // Check for pback madness, and if so switch back to the // normal buffers and jet outta here before expensive // fileops happen... @@ -357,8 +365,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { int_type __ret = traits_type::eof(); const bool __testin = _M_mode & ios_base::in; - if (__testin && !_M_writing) + if (__testin) { + if (_M_writing) + { + __ret = overflow(); + if (__ret == traits_type::eof()) + return __ret; + _M_set_buffer(-1); + _M_writing = false; + } // Remember whether the pback buffer is active, otherwise below // we may try to store in it a second char (libstdc++/9761). const bool __testpb = _M_pback_init; @@ -410,8 +426,16 @@ _GLIBCXX_BEGIN_NAMESPACE(std) int_type __ret = traits_type::eof(); const bool __testeof = traits_type::eq_int_type(__c, __ret); const bool __testout = _M_mode & ios_base::out; - if (__testout && !_M_reading) + if (__testout) { + if (_M_reading) + { + _M_destroy_pback(); + const int __gptr_off = _M_get_ext_pos(_M_state_last); + if (_M_seek(__gptr_off, ios_base::cur, _M_state_last) + == pos_type(off_type(-1))) + return __ret; + } if (this->pbase() < this->pptr()) { // If appropriate, append the overflow char. @@ -691,12 +715,20 @@ _GLIBCXX_BEGIN_NAMESPACE(std) if (__width < 0) __width = 0; - pos_type __ret = pos_type(off_type(-1)); + pos_type __ret = pos_type(off_type(-1)); const bool __testfail = __off != 0 && __width <= 0; if (this->is_open() && !__testfail) { + // tellg and tellp queries do not affect any state, unless + // ! always_noconv and the put sequence is not empty. + // In that case, determining the position requires converting the + // put sequence. That doesn't use ext_buf, so requires a flush. + bool __no_movement = __way == ios_base::cur && __off == 0 + && (!_M_writing || _M_codecvt->always_noconv()); + // Ditch any pback buffers to avoid confusion. - _M_destroy_pback(); + if (!__no_movement) + _M_destroy_pback(); // Correct state at destination. Note that this is the correct // state for the current position during output, because @@ -707,24 +739,23 @@ _GLIBCXX_BEGIN_NAMESPACE(std) off_type __computed_off = __off * __width; if (_M_reading && __way == ios_base::cur) { - if (_M_codecvt->always_noconv()) - __computed_off += this->gptr() - this->egptr(); - else + __state = _M_state_last; + __computed_off += _M_get_ext_pos(__state); + } + if (!__no_movement) + __ret = _M_seek(__computed_off, __way, __state); + else + { + if (_M_writing) + __computed_off = this->pptr() - this->pbase(); + + off_type __file_off = _M_file.seekoff(0, ios_base::cur); + if (__file_off != off_type(-1)) { - // Calculate offset from _M_ext_buf that corresponds - // to gptr(). Note: uses _M_state_last, which - // corresponds to eback(). - const int __gptr_off = - _M_codecvt->length(_M_state_last, _M_ext_buf, _M_ext_next, - this->gptr() - this->eback()); - __computed_off += _M_ext_buf + __gptr_off - _M_ext_end; - - // _M_state_last is modified by codecvt::length() so - // it now corresponds to gptr(). - __state = _M_state_last; + __ret = __file_off + __computed_off; + __ret.state(__state); } } - __ret = _M_seek(__computed_off, __way, __state); } return __ret; } @@ -756,21 +787,42 @@ _GLIBCXX_BEGIN_NAMESPACE(std) pos_type __ret = pos_type(off_type(-1)); if (_M_terminate_output()) { - // Returns pos_type(off_type(-1)) in case of failure. - __ret = pos_type(_M_file.seekoff(__off, __way)); - if (__ret != pos_type(off_type(-1))) + off_type __file_off = _M_file.seekoff(__off, __way); + if (__file_off != off_type(-1)) { _M_reading = false; _M_writing = false; _M_ext_next = _M_ext_end = _M_ext_buf; _M_set_buffer(-1); _M_state_cur = __state; + __ret = __file_off; __ret.state(_M_state_cur); } } return __ret; } + // Returns the distance from the end of the ext buffer to the point + // corresponding to gptr(). This is a negative value. Updates __state + // from eback() correspondence to gptr(). + template<typename _CharT, typename _Traits> + int basic_filebuf<_CharT, _Traits>:: + _M_get_ext_pos(__state_type& __state) + { + if (_M_codecvt->always_noconv()) + return this->gptr() - this->egptr(); + else + { + // Calculate offset from _M_ext_buf that corresponds to + // gptr(). Precondition: __state == _M_state_last, which + // corresponds to eback(). + const int __gptr_off = + _M_codecvt->length(__state, _M_ext_buf, _M_ext_next, + this->gptr() - this->eback()); + return _M_ext_buf + __gptr_off - _M_ext_end; + } + } + template<typename _CharT, typename _Traits> bool basic_filebuf<_CharT, _Traits>:: diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h index 36396878892..a132cce7689 100644 --- a/libstdc++-v3/include/bits/functional_hash.h +++ b/libstdc++-v3/include/bits/functional_hash.h @@ -33,7 +33,6 @@ #pragma GCC system_header #include <bits/c++config.h> -#include <bits/stl_function.h> namespace std { @@ -45,9 +44,16 @@ namespace std * @{ */ + template<typename _Result, typename _Arg> + struct __hash_base + { + typedef _Result result_type; + typedef _Arg argument_type; + }; + /// Primary class template hash. template<typename _Tp> - struct hash : public std::unary_function<_Tp, size_t> + struct hash : public __hash_base<size_t, _Tp> { size_t operator()(_Tp __val) const; @@ -55,7 +61,7 @@ namespace std /// Partial specializations for pointer types. template<typename _Tp> - struct hash<_Tp*> : public std::unary_function<_Tp*, size_t> + struct hash<_Tp*> : public __hash_base<size_t, _Tp*> { size_t operator()(_Tp* __p) const diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index c489b447ca1..74c2e85fd70 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -1038,7 +1038,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) /// std::hash specialization for vector<bool>. template<typename _Alloc> struct hash<_GLIBCXX_STD_D::vector<bool, _Alloc>> - : public std::unary_function<_GLIBCXX_STD_D::vector<bool, _Alloc>, size_t> + : public __hash_base<size_t, _GLIBCXX_STD_D::vector<bool, _Alloc>> { size_t operator()(const _GLIBCXX_STD_D::vector<bool, _Alloc>& __b) const; diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath index 02ca6af744b..3469b3884e8 100644 --- a/libstdc++-v3/include/c_global/cmath +++ b/libstdc++-v3/include/c_global/cmath @@ -76,20 +76,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) - // Forward declaration of a helper function. This really should be - // an `exported' forward declaration. - template<typename _Tp> - _Tp __cmath_power(_Tp, unsigned int); - - template<typename _Tp> - inline _Tp - __pow_helper(_Tp __x, int __n) - { - return __n < 0 - ? _Tp(1)/__cmath_power(__x, -__n) - : __cmath_power(__x, __n); - } - inline double abs(double __x) { return __builtin_fabs(__x); } @@ -859,10 +845,6 @@ _GLIBCXX_END_NAMESPACE #endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */ #endif -#ifndef _GLIBCXX_EXPORT_TEMPLATE -# include <bits/cmath.tcc> -#endif - #ifdef __GXX_EXPERIMENTAL_CXX0X__ # if defined(_GLIBCXX_INCLUDE_AS_TR1) # error C++0x header cannot be included from TR1 header diff --git a/libstdc++-v3/include/c_global/cmath.tcc b/libstdc++-v3/include/c_global/cmath.tcc deleted file mode 100644 index 9f4c853a8ea..00000000000 --- a/libstdc++-v3/include/c_global/cmath.tcc +++ /dev/null @@ -1,55 +0,0 @@ -// -*- C++ -*- C math library. - -// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 -// 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 3, 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. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// <http://www.gnu.org/licenses/>. - -// This file was written by Gabriel Dos Reis <gdr@codesourcery.com> - -/** @file cmath.tcc - * This is a Standard C++ Library file. - */ - -#ifndef _GLIBCXX_CMATH_TCC -#define _GLIBCXX_CMATH_TCC 1 - -_GLIBCXX_BEGIN_NAMESPACE(std) - - template<typename _Tp> - inline _Tp - __cmath_power(_Tp __x, unsigned int __n) - { - _Tp __y = __n % 2 ? __x : _Tp(1); - - while (__n >>= 1) - { - __x = __x * __x; - if (__n % 2) - __y = __y * __x; - } - - return __y; - } - -_GLIBCXX_END_NAMESPACE - -#endif diff --git a/libstdc++-v3/include/c_std/cmath b/libstdc++-v3/include/c_std/cmath index e97089664d9..fcdfa15b95c 100644 --- a/libstdc++-v3/include/c_std/cmath +++ b/libstdc++-v3/include/c_std/cmath @@ -77,10 +77,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) - // Forward declaration of a helper function. This really should be - // an `exported' forward declaration. - template<typename _Tp> _Tp __cmath_power(_Tp, unsigned int); - inline double abs(double __x) { return __builtin_fabs(__x); } @@ -344,15 +340,6 @@ _GLIBCXX_BEGIN_NAMESPACE(std) modf(long double __x, long double* __iptr) { return __builtin_modfl(__x, __iptr); } - template<typename _Tp> - inline _Tp - __pow_helper(_Tp __x, int __n) - { - return __n < 0 - ? _Tp(1)/__cmath_power(__x, -__n) - : __cmath_power(__x, __n); - } - using ::pow; inline float @@ -590,8 +577,4 @@ _GLIBCXX_END_NAMESPACE #endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */ #endif -#ifndef _GLIBCXX_EXPORT_TEMPLATE -# include <bits/cmath.tcc> -#endif - #endif diff --git a/libstdc++-v3/include/c_std/cmath.tcc b/libstdc++-v3/include/c_std/cmath.tcc deleted file mode 100644 index 9f4c853a8ea..00000000000 --- a/libstdc++-v3/include/c_std/cmath.tcc +++ /dev/null @@ -1,55 +0,0 @@ -// -*- C++ -*- C math library. - -// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 -// 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 3, 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. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// <http://www.gnu.org/licenses/>. - -// This file was written by Gabriel Dos Reis <gdr@codesourcery.com> - -/** @file cmath.tcc - * This is a Standard C++ Library file. - */ - -#ifndef _GLIBCXX_CMATH_TCC -#define _GLIBCXX_CMATH_TCC 1 - -_GLIBCXX_BEGIN_NAMESPACE(std) - - template<typename _Tp> - inline _Tp - __cmath_power(_Tp __x, unsigned int __n) - { - _Tp __y = __n % 2 ? __x : _Tp(1); - - while (__n >>= 1) - { - __x = __x * __x; - if (__n % 2) - __y = __y * __x; - } - - return __y; - } - -_GLIBCXX_END_NAMESPACE - -#endif diff --git a/libstdc++-v3/include/debug/bitset b/libstdc++-v3/include/debug/bitset index f452062e154..017c9e020dd 100644 --- a/libstdc++-v3/include/debug/bitset +++ b/libstdc++-v3/include/debug/bitset @@ -385,7 +385,7 @@ namespace __debug /// std::hash specialization for bitset. template<size_t _Nb> struct hash<__debug::bitset<_Nb>> - : public std::unary_function<__debug::bitset<_Nb>, size_t> + : public __hash_base<size_t, __debug::bitset<_Nb>> { size_t operator()(const __debug::bitset<_Nb>& __b) const diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector index b0846b8f42e..9004f2902ae 100644 --- a/libstdc++-v3/include/debug/vector +++ b/libstdc++-v3/include/debug/vector @@ -584,7 +584,7 @@ namespace __debug /// std::hash specialization for vector<bool>. template<typename _Alloc> struct hash<__debug::vector<bool, _Alloc>> - : public std::unary_function<__debug::vector<bool, _Alloc>, size_t> + : public __hash_base<size_t, __debug::vector<bool, _Alloc>> { size_t operator()(const __debug::vector<bool, _Alloc>& __b) const diff --git a/libstdc++-v3/include/ext/throw_allocator.h b/libstdc++-v3/include/ext/throw_allocator.h index 669d433e272..cc344787e83 100644 --- a/libstdc++-v3/include/ext/throw_allocator.h +++ b/libstdc++-v3/include/ext/throw_allocator.h @@ -737,8 +737,8 @@ namespace std size_t operator()(const __gnu_cxx::throw_value_limit& __val) const { - std::hash<std::size_t> h; - size_t __result = h(__val._M_i); + std::hash<std::size_t> __h; + size_t __result = __h(__val._M_i); return __result; } }; @@ -751,8 +751,8 @@ namespace std size_t operator()(const __gnu_cxx::throw_value_random& __val) const { - std::hash<std::size_t> h; - size_t __result = h(__val._M_i); + std::hash<std::size_t> __h; + size_t __result = __h(__val._M_i); return __result; } }; diff --git a/libstdc++-v3/include/parallel/set_operations.h b/libstdc++-v3/include/parallel/set_operations.h index f6b076f0655..f552c1dda1b 100644 --- a/libstdc++-v3/include/parallel/set_operations.h +++ b/libstdc++-v3/include/parallel/set_operations.h @@ -103,11 +103,11 @@ namespace __gnu_parallel } _DifferenceType - __count(_IIter __a, _IIter __b, _IIter __c, _IIter d) const + __count(_IIter __a, _IIter __b, _IIter __c, _IIter __d) const { _DifferenceType __counter = 0; - while (__a != __b && __c != d) + while (__a != __b && __c != __d) { if (_M_comp(*__a, *__c)) { @@ -126,12 +126,12 @@ namespace __gnu_parallel } } - return __counter + (__b - __a) + (d - __c); + return __counter + (__b - __a) + (__d - __c); } _OutputIterator - __first_empty(_IIter __c, _IIter d, _OutputIterator __out) const - { return std::copy(__c, d, __out); } + __first_empty(_IIter __c, _IIter __d, _OutputIterator __out) const + { return std::copy(__c, __d, __out); } _OutputIterator __second_empty(_IIter __a, _IIter __b, _OutputIterator __out) const @@ -153,10 +153,10 @@ namespace __gnu_parallel _Compare _M_comp; _OutputIterator - _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter d, + _M_invoke(_IIter __a, _IIter __b, _IIter __c, _IIter __d, _OutputIterator __r) const { - while (__a != __b && __c != d) + while (__a != __b && __c != __d) { if (_M_comp(*__a, *__c)) { @@ -177,11 +177,11 @@ namespace __gnu_parallel _DifferenceType __count(_IIter __a, _IIter __b, - _IIter __c, _IIter d) const + _IIter __c, _IIter __d) const { _DifferenceType __counter = 0; - while (__a != __b && __c != d) + while (__a != __b && __c != __d) { if (_M_comp(*__a, *__c)) { diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h index c19c9384be0..510a6552f52 100644 --- a/libstdc++-v3/include/precompiled/stdc++.h +++ b/libstdc++-v3/include/precompiled/stdc++.h @@ -1,6 +1,6 @@ // C++ includes used for precompiling -*- C++ -*- -// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -109,6 +109,7 @@ #include <system_error> #include <thread> #include <tuple> +#include <typeindex> #include <type_traits> #include <unordered_map> #include <unordered_set> diff --git a/libstdc++-v3/include/profile/bitset b/libstdc++-v3/include/profile/bitset index f6b8249a321..79175244bed 100644 --- a/libstdc++-v3/include/profile/bitset +++ b/libstdc++-v3/include/profile/bitset @@ -359,7 +359,7 @@ namespace __profile /// std::hash specialization for bitset. template<size_t _Nb> struct hash<__profile::bitset<_Nb>> - : public std::unary_function<__profile::bitset<_Nb>, size_t> + : public __hash_base<size_t, __profile::bitset<_Nb>> { size_t operator()(const __profile::bitset<_Nb>& __b) const diff --git a/libstdc++-v3/include/profile/impl/profiler_node.h b/libstdc++-v3/include/profile/impl/profiler_node.h index d22a3e16b48..86f541f59d7 100644 --- a/libstdc++-v3/include/profile/impl/profiler_node.h +++ b/libstdc++-v3/include/profile/impl/profiler_node.h @@ -148,7 +148,7 @@ namespace __gnu_profile __stack() const { return _M_stack; } - virtual void __write(FILE* f) const = 0; + virtual void __write(FILE* __f) const = 0; protected: __stack_t _M_stack; diff --git a/libstdc++-v3/include/profile/vector b/libstdc++-v3/include/profile/vector index 1bd4346ec67..cd04b515599 100644 --- a/libstdc++-v3/include/profile/vector +++ b/libstdc++-v3/include/profile/vector @@ -505,7 +505,7 @@ namespace __profile /// std::hash specialization for vector<bool>. template<typename _Alloc> struct hash<__profile::vector<bool, _Alloc>> - : public std::unary_function<__profile::vector<bool, _Alloc>, size_t> + : public __hash_base<size_t, __profile::vector<bool, _Alloc>> { size_t operator()(const __profile::vector<bool, _Alloc>& __b) const diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset index 909ed770735..d263fae645a 100644 --- a/libstdc++-v3/include/std/bitset +++ b/libstdc++-v3/include/std/bitset @@ -53,8 +53,8 @@ #define _GLIBCXX_BITSET_BITS_PER_WORD (__CHAR_BIT__ * sizeof(unsigned long)) #define _GLIBCXX_BITSET_WORDS(__n) \ - ((__n) < 1 ? 0 : ((__n) + _GLIBCXX_BITSET_BITS_PER_WORD - 1) \ - / _GLIBCXX_BITSET_BITS_PER_WORD) + ((__n) / _GLIBCXX_BITSET_BITS_PER_WORD + \ + ((__n) % _GLIBCXX_BITSET_BITS_PER_WORD == 0 ? 0 : 1)) _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) @@ -1495,7 +1495,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) /// std::hash specialization for bitset. template<size_t _Nb> struct hash<_GLIBCXX_STD_D::bitset<_Nb>> - : public std::unary_function<_GLIBCXX_STD_D::bitset<_Nb>, size_t> + : public __hash_base<size_t, _GLIBCXX_STD_D::bitset<_Nb>> { size_t operator()(const _GLIBCXX_STD_D::bitset<_Nb>& __b) const @@ -1507,7 +1507,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) template<> struct hash<_GLIBCXX_STD_D::bitset<0>> - : public std::unary_function<_GLIBCXX_STD_D::bitset<0>, size_t> + : public __hash_base<size_t, _GLIBCXX_STD_D::bitset<0>> { size_t operator()(const _GLIBCXX_STD_D::bitset<0>&) const diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex index 31c44363137..93056510e08 100644 --- a/libstdc++-v3/include/std/complex +++ b/libstdc++-v3/include/std/complex @@ -951,12 +951,32 @@ _GLIBCXX_BEGIN_NAMESPACE(std) // raised to the __y-th power. The branch // cut is on the negative axis. #ifndef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _Tp> + complex<_Tp> + __complex_pow_unsigned(complex<_Tp> __x, unsigned __n) + { + complex<_Tp> __y = __n % 2 ? __x : complex<_Tp>(1); + + while (__n >>= 1) + { + __x *= __x; + if (__n % 2) + __y *= __x; + } + + return __y; + } + // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 844. complex pow return type is ambiguous. template<typename _Tp> inline complex<_Tp> pow(const complex<_Tp>& __z, int __n) - { return std::__pow_helper(__z, __n); } + { + return __n < 0 + ? complex<_Tp>(1) / std::__complex_pow_unsigned(__z, -__n) + : std::__complex_pow_unsigned(__z, __n); + } #endif template<typename _Tp> diff --git a/libstdc++-v3/include/std/fstream b/libstdc++-v3/include/std/fstream index 00690bee938..0ffd33d3186 100644 --- a/libstdc++-v3/include/std/fstream +++ b/libstdc++-v3/include/std/fstream @@ -351,9 +351,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std) seekpos(pos_type __pos, ios_base::openmode __mode = ios_base::in | ios_base::out); - // Common code for seekoff and seekpos + // Common code for seekoff, seekpos, and overflow pos_type _M_seek(off_type __off, ios_base::seekdir __way, __state_type __state); + + int + _M_get_ext_pos(__state_type &__state); virtual int sync(); diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error index 2c968e92e90..ce4e23825a3 100644 --- a/libstdc++-v3/include/std/system_error +++ b/libstdc++-v3/include/std/system_error @@ -353,7 +353,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) /// std::hash specialization for error_code. template<> struct hash<error_code> - : public std::unary_function<error_code, size_t> + : public __hash_base<size_t, error_code> { size_t operator()(const error_code& __e) const diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index 38e9d45a46d..d5bbf6e0146 100644 --- a/libstdc++-v3/include/std/thread +++ b/libstdc++-v3/include/std/thread @@ -56,9 +56,6 @@ namespace std * @{ */ - template<typename _Tp> - struct hash; - /// thread class thread { @@ -224,7 +221,7 @@ namespace std /// std::hash specialization for thread::id. template<> struct hash<thread::id> - : public std::unary_function<thread::id, size_t> + : public __hash_base<size_t, thread::id> { size_t operator()(const thread::id& __id) const diff --git a/libstdc++-v3/include/std/typeindex b/libstdc++-v3/include/std/typeindex new file mode 100644 index 00000000000..44836f67ea3 --- /dev/null +++ b/libstdc++-v3/include/std/typeindex @@ -0,0 +1,105 @@ +// C++0x typeindex -*- C++ -*- + +// Copyright (C) 2010 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 3, 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file include/typeindex + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_TYPEINDEX +#define _GLIBCXX_TYPEINDEX 1 + +#pragma GCC system_header + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +# include <bits/c++0x_warning.h> +#else + +#include <typeinfo> + +namespace std +{ + /** + @brief The class type_index provides a simple wrapper for type_info + which can be used as an index type in associative containers (23.6) + and in unordered associative containers (23.7). + */ + struct type_index + { + type_index(const type_info& __rhs) + : _M_target(&__rhs) { } + + bool + operator==(const type_index& __rhs) const + { return *_M_target == *__rhs._M_target; } + + bool + operator!=(const type_index& __rhs) const + { return *_M_target != *__rhs._M_target; } + + bool + operator<(const type_index& __rhs) const + { return _M_target->before(*__rhs._M_target); } + + bool + operator<=(const type_index& __rhs) const + { return !__rhs._M_target->before(*_M_target); } + + bool + operator>(const type_index& __rhs) const + { return __rhs._M_target->before(*_M_target); } + + bool + operator>=(const type_index& __rhs) const + { return !_M_target->before(*__rhs._M_target); } + + size_t + hash_code() const + { return _M_target->hash_code(); } + + const char* + name() const + { return _M_target->name(); } + + private: + const type_info* _M_target; + }; + + template<typename _Tp> struct hash; + + /// std::hash specialization for type_index. + template<> + struct hash<type_index> + { + typedef size_t result_type; + typedef type_index argument_type; + + size_t + operator()(const type_index& __ti) const + { return __ti.hash_code(); } + }; +} + +#endif // __GXX_EXPERIMENTAL_CXX0X__ + +#endif // _GLIBCXX_TYPEINDEX diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am index 0b2fd0bc786..5fbad83049a 100644 --- a/libstdc++-v3/libsupc++/Makefile.am +++ b/libstdc++-v3/libsupc++/Makefile.am @@ -69,6 +69,7 @@ sources = \ function_type_info.cc \ fundamental_type_info.cc \ guard.cc \ + hash_bytes.cc \ new_handler.cc \ new_op.cc \ new_opnt.cc \ diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in index 7c00b672608..394bd42afe0 100644 --- a/libstdc++-v3/libsupc++/Makefile.in +++ b/libstdc++-v3/libsupc++/Makefile.in @@ -95,10 +95,10 @@ am__objects_1 = array_type_info.lo atexit_arm.lo bad_cast.lo \ eh_globals.lo eh_personality.lo eh_ptr.lo eh_term_handler.lo \ eh_terminate.lo eh_throw.lo eh_type.lo eh_unex_handler.lo \ enum_type_info.lo function_type_info.lo \ - fundamental_type_info.lo guard.lo new_handler.lo new_op.lo \ - new_opnt.lo new_opv.lo new_opvnt.lo pbase_type_info.lo \ - pmem_type_info.lo pointer_type_info.lo pure.lo \ - si_class_type_info.lo tinfo.lo tinfo2.lo vec.lo \ + fundamental_type_info.lo guard.lo hash_bytes.lo new_handler.lo \ + new_op.lo new_opnt.lo new_opv.lo new_opvnt.lo \ + pbase_type_info.lo pmem_type_info.lo pointer_type_info.lo \ + pure.lo si_class_type_info.lo tinfo.lo tinfo2.lo vec.lo \ vmi_class_type_info.lo vterminate.lo @GLIBCXX_HOSTED_TRUE@am__objects_2 = cp-demangle.lo am_libsupc___la_OBJECTS = $(am__objects_1) $(am__objects_2) @@ -364,6 +364,7 @@ sources = \ function_type_info.cc \ fundamental_type_info.cc \ guard.cc \ + hash_bytes.cc \ new_handler.cc \ new_op.cc \ new_opnt.cc \ diff --git a/libstdc++-v3/src/hash_bytes.cc b/libstdc++-v3/libsupc++/hash_bytes.cc index 5dfa1eec1d6..e9a3812664e 100644 --- a/libstdc++-v3/src/hash_bytes.cc +++ b/libstdc++-v3/libsupc++/hash_bytes.cc @@ -32,8 +32,7 @@ // function apears to be better in both speed and hash quality, and // FNV is provided primarily for backward compatibility. -#include <cstring> -#include <bits/functional_hash.h> +#include <bits/c++config.h> namespace { @@ -41,15 +40,16 @@ namespace unaligned_load(const char* p) { std::size_t result; - std::memcpy(&result, p, sizeof(result)); + __builtin_memcpy(&result, p, sizeof(result)); return result; } +#if __SIZEOF_SIZE_T__ == 8 // Loads n bytes, where 1 <= n < 8. inline std::size_t load_bytes(const char* p, int n) { - size_t result = 0; + std::size_t result = 0; --n; do result = (result << 8) + static_cast<unsigned char>(p[n]); @@ -60,6 +60,7 @@ namespace inline std::size_t shift_mix(std::size_t v) { return v ^ (v >> 47);} +#endif } namespace std diff --git a/libstdc++-v3/libsupc++/typeinfo b/libstdc++-v3/libsupc++/typeinfo index 1a4736e1cba..8030eb40e2f 100644 --- a/libstdc++-v3/libsupc++/typeinfo +++ b/libstdc++-v3/libsupc++/typeinfo @@ -78,6 +78,11 @@ namespace __cxxabiv1 namespace std { +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + size_t + _Hash_bytes(const void* __ptr, size_t __len, size_t __seed); +#endif + /** * @brief Part of RTTI. * @@ -135,6 +140,18 @@ namespace std bool operator!=(const type_info& __arg) const { return !operator==(__arg); } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + size_t hash_code() const throw() + { +# if !__GXX_MERGED_TYPEINFO_NAMES + return _Hash_bytes(name(), __builtin_strlen(name()), + static_cast<size_t>(0xc70f6907UL)); +# else + return reinterpret_cast<size_t>(__name); +# endif + } +#endif // __GXX_EXPERIMENTAL_CXX0X__ + // Return true if this is a pointer type of some kind virtual bool __is_pointer_p() const; diff --git a/libstdc++-v3/src/Makefile.am b/libstdc++-v3/src/Makefile.am index d5194c3366e..d4efaf2e530 100644 --- a/libstdc++-v3/src/Makefile.am +++ b/libstdc++-v3/src/Makefile.am @@ -179,7 +179,6 @@ sources = \ hash_tr1.cc \ hashtable_c++0x.cc \ hashtable_tr1.cc \ - hash_bytes.cc \ ios.cc \ ios_failure.cc \ ios_init.cc \ @@ -310,11 +309,6 @@ hashtable_c++0x.lo: hashtable_c++0x.cc hashtable_c++0x.o: hashtable_c++0x.cc $(CXXCOMPILE) -std=gnu++0x -c $< -hash_bytes.lo: hash_bytes.cc - $(LTCXXCOMPILE) -std=gnu++0x -c $< -hash_bytes.o: hash_bytes.cc - $(CXXCOMPILE) -std=gnu++0x -c $< - limits.lo: limits.cc $(LTCXXCOMPILE) -std=gnu++0x -c $< limits.o: limits.cc @@ -421,13 +415,16 @@ endif debugdir = debug # Build a set of debug objects here. +# Take care to fix all possibly-relative paths. stamp-debug: if test ! -d ${debugdir}; then \ mkdir -p ${debugdir}; \ (cd ${debugdir}; \ sed -e 's/top_builddir = \.\./top_builddir = ..\/../' \ + -e 's/top_build_prefix = \.\./top_build_prefix = ..\/../' \ -e 's/srcdir = \.\./srcdir = ..\/../' \ -e 's/glibcxx_basedir = \.\./glibcxx_basedir = ..\/../' \ + -e 's/MKDIR_P = \.\./MKDIR_P = ..\/../' \ -e 's/all-local: build_debug/all-local:/' \ -e 's/install-data-local: install_debug/install-data-local:/' \ < ../Makefile > Makefile) ; \ diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in index 92390975740..647124e4674 100644 --- a/libstdc++-v3/src/Makefile.in +++ b/libstdc++-v3/src/Makefile.in @@ -100,18 +100,17 @@ am__objects_5 = atomic.lo bitmap_allocator.lo pool_allocator.lo \ compatibility-c++0x.lo compatibility-debug_list.lo \ compatibility-list.lo complex_io.lo ctype.lo debug.lo \ functexcept.lo globals_io.lo hash_c++0x.lo hash_tr1.lo \ - hashtable_c++0x.lo hashtable_tr1.lo hash_bytes.lo ios.lo \ - ios_failure.lo ios_init.lo ios_locale.lo limits.lo list.lo \ - debug_list.lo locale.lo locale_init.lo locale_facets.lo \ - localename.lo math_stubs_float.lo math_stubs_long_double.lo \ - stdexcept.lo strstream.lo system_error.lo tree.lo \ - allocator-inst.lo concept-inst.lo fstream-inst.lo ext-inst.lo \ - ios-inst.lo iostream-inst.lo istream-inst.lo istream.lo \ - locale-inst.lo misc-inst.lo ostream-inst.lo sstream-inst.lo \ - streambuf-inst.lo streambuf.lo string-inst.lo valarray-inst.lo \ - wlocale-inst.lo wstring-inst.lo mutex.lo condition_variable.lo \ - chrono.lo thread.lo future.lo $(am__objects_1) \ - $(am__objects_4) + hashtable_c++0x.lo hashtable_tr1.lo ios.lo ios_failure.lo \ + ios_init.lo ios_locale.lo limits.lo list.lo debug_list.lo \ + locale.lo locale_init.lo locale_facets.lo localename.lo \ + math_stubs_float.lo math_stubs_long_double.lo stdexcept.lo \ + strstream.lo system_error.lo tree.lo allocator-inst.lo \ + concept-inst.lo fstream-inst.lo ext-inst.lo ios-inst.lo \ + iostream-inst.lo istream-inst.lo istream.lo locale-inst.lo \ + misc-inst.lo ostream-inst.lo sstream-inst.lo streambuf-inst.lo \ + streambuf.lo string-inst.lo valarray-inst.lo wlocale-inst.lo \ + wstring-inst.lo mutex.lo condition_variable.lo chrono.lo \ + thread.lo future.lo $(am__objects_1) $(am__objects_4) am_libstdc___la_OBJECTS = $(am__objects_5) libstdc___la_OBJECTS = $(am_libstdc___la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) @@ -384,7 +383,6 @@ sources = \ hash_tr1.cc \ hashtable_c++0x.cc \ hashtable_tr1.cc \ - hash_bytes.cc \ ios.cc \ ios_failure.cc \ ios_init.cc \ @@ -887,11 +885,6 @@ hashtable_c++0x.lo: hashtable_c++0x.cc hashtable_c++0x.o: hashtable_c++0x.cc $(CXXCOMPILE) -std=gnu++0x -c $< -hash_bytes.lo: hash_bytes.cc - $(LTCXXCOMPILE) -std=gnu++0x -c $< -hash_bytes.o: hash_bytes.cc - $(CXXCOMPILE) -std=gnu++0x -c $< - limits.lo: limits.cc $(LTCXXCOMPILE) -std=gnu++0x -c $< limits.o: limits.cc @@ -946,13 +939,16 @@ future.o: future.cc @GLIBCXX_BUILD_DEBUG_FALSE@install-data-local: # Build a set of debug objects here. +# Take care to fix all possibly-relative paths. stamp-debug: if test ! -d ${debugdir}; then \ mkdir -p ${debugdir}; \ (cd ${debugdir}; \ sed -e 's/top_builddir = \.\./top_builddir = ..\/../' \ + -e 's/top_build_prefix = \.\./top_build_prefix = ..\/../' \ -e 's/srcdir = \.\./srcdir = ..\/../' \ -e 's/glibcxx_basedir = \.\./glibcxx_basedir = ..\/../' \ + -e 's/MKDIR_P = \.\./MKDIR_P = ..\/../' \ -e 's/all-local: build_debug/all-local:/' \ -e 's/install-data-local: install_debug/install-data-local:/' \ < ../Makefile > Makefile) ; \ diff --git a/libstdc++-v3/testsuite/18_support/type_info/hash_code.cc b/libstdc++-v3/testsuite/18_support/type_info/hash_code.cc new file mode 100644 index 00000000000..2d4c65bc593 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/type_info/hash_code.cc @@ -0,0 +1,79 @@ +// { dg-options "-std=gnu++0x" } + +// 2010-09-21 Paolo Carlini <paolo.carlini@oracle.com> +// +// Copyright (C) 2010 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 3, 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 COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <typeinfo> +#include <testsuite_hooks.h> + +void test01() +{ + bool test __attribute__((unused)) = true; + using namespace std; + + class Abraca { }; + Abraca a1, a2_; + + typedef const Abraca cAbraca; + cAbraca a2 = a2_; + + class Dabra { }; + Dabra d1; + + const type_info& to01 = typeid(int); + const type_info& to02 = typeid(double); + VERIFY( to01 != to02 ); + VERIFY( to01.hash_code() != to02.hash_code() ); + + const type_info& to03 = typeid(a1); + const type_info& to04 = typeid(a2); + VERIFY( to03 == to04 ); + VERIFY( to03.hash_code() == to04.hash_code() ); + + const type_info& to05 = typeid(Abraca); + const type_info& to06 = typeid(cAbraca); + VERIFY( to05 == to06 ); + VERIFY( to05.hash_code() == to06.hash_code() ); + + const type_info& to07 = typeid(Abraca); + const type_info& to08 = typeid(a2); + VERIFY( to07 == to08 ); + VERIFY( to07.hash_code() == to08.hash_code() ); + + const type_info& to09 = typeid(Abraca); + const type_info& to10 = typeid(const Abraca&); + VERIFY( to09 == to10 ); + VERIFY( to09.hash_code() == to10.hash_code() ); + + const type_info& to11 = typeid(Abraca); + const type_info& to12 = typeid(Dabra); + VERIFY( to11 != to12 ); + VERIFY( to11.hash_code() != to12.hash_code() ); + + const type_info& to13 = typeid(a1); + const type_info& to14 = typeid(d1); + VERIFY( to13 != to14 ); + VERIFY( to13.hash_code() != to14.hash_code() ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/typeindex/comparison_operators.cc b/libstdc++-v3/testsuite/20_util/typeindex/comparison_operators.cc new file mode 100644 index 00000000000..5ca53967d4d --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/typeindex/comparison_operators.cc @@ -0,0 +1,88 @@ +// { dg-options "-std=gnu++0x" } + +// 2010-09-22 Paolo Carlini <paolo.carlini@oracle.com> +// +// Copyright (C) 2010 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 3, 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 COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <typeindex> +#include <testsuite_hooks.h> + +#define TEST3(TI1, TI2, TO1, TO2) \ + VERIFY( (TI1 == TI2) == (TO1 == TO2) ); \ + VERIFY( (TI1 != TI2) == (TO1 != TO2) ); \ + VERIFY( (TI1 < TI2) == (TO1.before(TO2)) ); \ + VERIFY( (TI1 <= TI2) == (!TO2.before(TO1)) ); \ + VERIFY( (TI1 > TI2) == (TO2.before(TO1)) ); \ + VERIFY( (TI1 >= TI2) == (!TO1.before(TO2)) ); + +#define TEST2(TI, TO) \ + TEST3(TI, ti1, TO, to1) \ + TEST3(TI, ti2, TO, to2) \ + TEST3(TI, ti3, TO, to3) \ + TEST3(TI, ti4, TO, to4) \ + TEST3(TI, ti5, TO, to5) \ + TEST3(TI, ti6, TO, to6) \ + TEST3(TI, ti7, TO, to7) + +#define TEST \ + TEST2(ti1, to1) \ + TEST2(ti2, to2) \ + TEST2(ti3, to3) \ + TEST2(ti4, to4) \ + TEST2(ti5, to5) \ + TEST2(ti6, to6) \ + TEST2(ti7, to7) + +void test01() +{ + bool test __attribute__((unused)) = true; + using namespace std; + + class Abraca { }; + Abraca a1, a2_; + const Abraca a2 = a2_; + + const type_info& to1 = typeid(int); + const type_index ti1(to1); + + const type_info& to2 = typeid(double); + const type_index ti2(to2); + + const type_info& to3 = typeid(Abraca); + const type_index ti3(to3); + + const type_info& to4 = typeid(const Abraca); + const type_index ti4(to4); + + const type_info& to5 = typeid(const Abraca&); + const type_index ti5(to5); + + const type_info& to6 = typeid(a1); + const type_index ti6(to6); + + const type_info& to7 = typeid(a2); + const type_index ti7(to7); + + TEST +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/typeindex/hash.cc b/libstdc++-v3/testsuite/20_util/typeindex/hash.cc new file mode 100644 index 00000000000..2468ea6933e --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/typeindex/hash.cc @@ -0,0 +1,60 @@ +// { dg-options "-std=gnu++0x" } + +// 2010-09-22 Paolo Carlini <paolo.carlini@oracle.com> +// +// Copyright (C) 2010 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 3, 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 COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <typeindex> +#include <testsuite_hooks.h> + +void test01() +{ + bool test __attribute__((unused)) = true; + using namespace std; + + class Abraca { }; + Abraca a1, a2_; + const Abraca a2 = a2_; + + const type_index ti1(typeid(int)); + VERIFY( hash<type_index>()(ti1) == ti1.hash_code() ); + + const type_index ti2(typeid(double)); + VERIFY( hash<type_index>()(ti2) == ti2.hash_code() ); + + const type_index ti3(typeid(Abraca)); + VERIFY( hash<type_index>()(ti3) == ti3.hash_code() ); + + const type_index ti4(typeid(const Abraca)); + VERIFY( hash<type_index>()(ti4) == ti4.hash_code() ); + + const type_index ti5(typeid(const Abraca&)); + VERIFY( hash<type_index>()(ti5) == ti5.hash_code() ); + + const type_index ti6(typeid(a1)); + VERIFY( hash<type_index>()(ti6) == ti6.hash_code() ); + + const type_index ti7(typeid(a2)); + VERIFY( hash<type_index>()(ti7) == ti7.hash_code() ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/typeindex/hash_code.cc b/libstdc++-v3/testsuite/20_util/typeindex/hash_code.cc new file mode 100644 index 00000000000..f12b6cbb943 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/typeindex/hash_code.cc @@ -0,0 +1,67 @@ +// { dg-options "-std=gnu++0x" } + +// 2010-09-22 Paolo Carlini <paolo.carlini@oracle.com> +// +// Copyright (C) 2010 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 3, 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 COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <typeindex> +#include <testsuite_hooks.h> + +void test01() +{ + bool test __attribute__((unused)) = true; + using namespace std; + + class Abraca { }; + Abraca a1, a2_; + const Abraca a2 = a2_; + + const type_info& to1 = typeid(int); + const type_index ti1(to1); + VERIFY( ti1.hash_code() == to1.hash_code() ); + + const type_info& to2 = typeid(double); + const type_index ti2(to2); + VERIFY( ti2.hash_code() == to2.hash_code() ); + + const type_info& to3 = typeid(Abraca); + const type_index ti3(to3); + VERIFY( ti3.hash_code() == to3.hash_code() ); + + const type_info& to4 = typeid(const Abraca); + const type_index ti4(to4); + VERIFY( ti4.hash_code() == to4.hash_code() ); + + const type_info& to5 = typeid(const Abraca&); + const type_index ti5(to5); + VERIFY( ti5.hash_code() == to5.hash_code() ); + + const type_info& to6 = typeid(a1); + const type_index ti6(to6); + VERIFY( ti6.hash_code() == to6.hash_code() ); + + const type_info& to7 = typeid(a2); + const type_index ti7(to7); + VERIFY( ti7.hash_code() == to7.hash_code() ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/typeindex/name.cc b/libstdc++-v3/testsuite/20_util/typeindex/name.cc new file mode 100644 index 00000000000..fa6e6945ceb --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/typeindex/name.cc @@ -0,0 +1,67 @@ +// { dg-options "-std=gnu++0x" } + +// 2010-09-22 Paolo Carlini <paolo.carlini@oracle.com> +// +// Copyright (C) 2010 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 3, 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 COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <typeindex> +#include <testsuite_hooks.h> + +void test01() +{ + bool test __attribute__((unused)) = true; + using namespace std; + + class Abraca { }; + Abraca a1, a2_; + const Abraca a2 = a2_; + + const type_info& to1 = typeid(int); + const type_index ti1(to1); + VERIFY( ti1.name() == to1.name() ); + + const type_info& to2 = typeid(double); + const type_index ti2(to2); + VERIFY( ti2.name() == to2.name() ); + + const type_info& to3 = typeid(Abraca); + const type_index ti3(to3); + VERIFY( ti3.name() == to3.name() ); + + const type_info& to4 = typeid(const Abraca); + const type_index ti4(to4); + VERIFY( ti4.name() == to4.name() ); + + const type_info& to5 = typeid(const Abraca&); + const type_index ti5(to5); + VERIFY( ti5.name() == to5.name() ); + + const type_info& to6 = typeid(a1); + const type_index ti6(to6); + VERIFY( ti6.name() == to6.name() ); + + const type_info& to7 = typeid(a2); + const type_index ti7(to7); + VERIFY( ti7.name() == to7.name() ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc b/libstdc++-v3/testsuite/23_containers/bitset/45713.cc index 0a11c43f397..8d369d63e18 100644 --- a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/char/1.cc +++ b/libstdc++-v3/testsuite/23_containers/bitset/45713.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2003, 2009 Free Software Foundation, Inc. +// Copyright (C) 2010 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 @@ -15,37 +15,11 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -// 27.8.1.4 Overridden virtual functions +// { dg-do compile } -#include <fstream> -#include <testsuite_hooks.h> +#include <bitset> -void test01() -{ - using namespace std; - - bool test __attribute__((unused)) = true; - const char* name = "tmp_sync_1"; - - filebuf fb; - - fb.open(name, ios_base::in | ios_base::out | ios_base::trunc); - fb.sputn("abc", 3); - - fb.pubseekoff(0, ios_base::beg); - fb.sputc('1'); - - // Sync can't be used to switch from write mode to read mode. - fb.pubsync(); - - filebuf::int_type c = fb.sbumpc(); - VERIFY( c == filebuf::traits_type::eof() ); - - fb.close(); -} - -int main() -{ - test01(); - return 0; -} +// libstdc++/45713 +#if __SIZEOF_SIZE_T__ >= 4 +int test[sizeof(std::bitset<0xffffffff>) != 1 ? 1 : -1]; +#endif diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/45628-2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/45628-2.cc new file mode 100644 index 00000000000..6e40a89aa60 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/45628-2.cc @@ -0,0 +1,103 @@ +// Copyright (C) 2010 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 3, 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 COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-require-fileio "" } + +#include <fstream> +#include <testsuite_hooks.h> +#include <testsuite_character.h> + +const char name_01[] = "tmp_seekoff_45628.tst"; + +unsigned underflows, overflows; + +class my_filebuf +: public std::basic_filebuf<__gnu_test::pod_uchar> +{ + virtual int_type + underflow() + { + ++underflows; + return std::basic_filebuf<__gnu_test::pod_uchar>::underflow(); + } + virtual int_type + overflow(int_type c) + { + ++overflows; + return std::basic_filebuf<__gnu_test::pod_uchar>::overflow(c); + } +}; + +// libstdc++/45628 +void test01() +{ + bool test __attribute__((unused)) = true; + + using __gnu_test::pod_uchar; + std::locale loc(std::locale::classic(), + new std::codecvt<my_filebuf::traits_type::char_type, char, + my_filebuf::traits_type::state_type>); + + my_filebuf::pos_type opos[3], ipos[3]; + my_filebuf q; + q.pubimbue(loc); + + q.open(name_01, std::ios_base::in | std::ios_base::out + | std::ios_base::trunc); + + q.sputc(pod_uchar::from<char>('a')); + opos[0] = q.pubseekoff(0, std::ios_base::cur); + q.sputc(pod_uchar::from<char>('b')); + opos[1] = q.pubseekoff(0, std::ios_base::cur); + q.sputc(pod_uchar::from<char>('c')); + opos[2] = q.pubseekoff(0, std::ios_base::cur); + + VERIFY( overflows <= 9 ); // pubseekoff calls overflow twice if converting. + // NB: checking opos==ipos is not very rigorous as long as it flushes, since + // all positions will be at initial state. + q.pubseekoff(0, std::ios_base::beg); + + q.sbumpc(); + VERIFY( underflows == 1 ); + + ipos[0] = q.pubseekoff(0, std::ios_base::cur); + VERIFY( ipos[0] == opos[0] ); + q.sbumpc(); + ipos[1] = q.pubseekoff(0, std::ios_base::cur); + VERIFY( ipos[1] == opos[1] ); + q.sbumpc(); + ipos[2] = q.pubseekoff(0, std::ios_base::cur); + VERIFY( ipos[2] == opos[2] ); + + VERIFY( underflows == 1 ); // pubseekoff never flushes get area + + // Bonus test: check automatic mode switches. + q.sputc(pod_uchar::from<char>('d')); + + q.pubseekpos( ipos[1] ); + q.sputc(pod_uchar::from<char>('e')); + + VERIFY( my_filebuf::traits_type::eq( + my_filebuf::traits_type::to_char_type(q.sgetc()), + pod_uchar::from<char>('d')) ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/4.cc index 9422f29f0d9..fe21b3a88e2 100644 --- a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/4.cc +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/4.cc @@ -31,7 +31,7 @@ void test01() typedef filebuf::pos_type pos_type; const char name[] = "tmp_seekoff-4.tst"; - const size_t size = 10; + const size_t size = 12; char buf[size]; streamsize n; @@ -46,7 +46,7 @@ void test01() VERIFY( n == 3 ); VERIFY( !memcmp(buf, "abc", 3) ); - fb.pubseekoff(0, ios_base::cur); + // Check read => write without pubseekoff(0, ios_base::cur) n = fb.sputn("ef", 2); VERIFY( n == 2 ); @@ -58,9 +58,17 @@ void test01() VERIFY( !memcmp(buf, "abcef", 5) ); fb.pubseekoff(0, ios_base::beg); - n = fb.sputn("ghijkl", 6); - VERIFY( n == 6 ); + n = fb.sputn("gh", 2); + VERIFY( n == 2 ); + + // Check write => read without pubseekoff(0, ios_base::cur) + + n = fb.sgetn( buf, 3 ); + VERIFY( !memcmp(buf, "cef", 3) ); + n = fb.sputn("ijkl", 4); + VERIFY( n == 4 ); + fb.pubseekoff(0, ios_base::beg); n = fb.sgetn(buf, 2); VERIFY( n == 2 ); @@ -72,8 +80,8 @@ void test01() fb.pubseekoff(0, ios_base::beg); n = fb.sgetn(buf, size); - VERIFY( n == 9 ); - VERIFY( !memcmp(buf, "ghijklmno", 9) ); + VERIFY( n == 12 ); + VERIFY( !memcmp(buf, "ghcefijklmno", 12) ); fb.close(); } diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/45628-1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/45628-1.cc new file mode 100644 index 00000000000..a80a3387656 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/char/45628-1.cc @@ -0,0 +1,79 @@ +// Copyright (C) 2010 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 3, 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 COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-require-fileio "" } + +#include <fstream> +#include <testsuite_hooks.h> + +const char name_01[] = "tmp_seekoff_45628.tst"; + +unsigned underflows, overflows; + +class my_filebuf +: public std::filebuf +{ + virtual int_type + underflow() + { + ++underflows; + return std::filebuf::underflow(); + } + virtual int_type + overflow(int_type c) + { + ++overflows; + return std::filebuf::overflow(c); + } +}; + +// libstdc++/45628 +void test01() +{ + bool test __attribute__((unused)) = true; + + my_filebuf q; + q.open(name_01, std::ios_base::in | std::ios_base::out + | std::ios_base::trunc); + + q.sputc('a'); + q.pubseekoff(0, std::ios_base::cur); + q.sputc('b'); + q.pubseekoff(0, std::ios_base::cur); + q.sputc('c'); + q.pubseekoff(0, std::ios_base::cur); + + VERIFY( overflows <= 1 ); // only initial sputc allowed to overflow + q.pubseekoff(0, std::ios_base::beg); + + q.sbumpc(); + VERIFY( underflows == 1 ); + + q.pubseekoff(0, std::ios_base::cur); + q.sbumpc(); + q.pubseekoff(0, std::ios_base::cur); + q.sbumpc(); + q.pubseekoff(0, std::ios_base::cur); + + VERIFY( underflows == 1 ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc index 95338cfde89..a6bba98ba84 100644 --- a/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/seekoff/wchar_t/4.cc @@ -31,7 +31,7 @@ void test01() typedef wfilebuf::pos_type pos_type; const char name[] = "tmp_seekoff-4.tst"; - const size_t size = 10; + const size_t size = 12; wchar_t buf[size]; streamsize n; @@ -46,7 +46,7 @@ void test01() VERIFY( n == 3 ); VERIFY( !wmemcmp(buf, L"abc", 3) ); - fb.pubseekoff(0, ios_base::cur); + // Check read => write without pubseekoff(0, ios_base::cur) n = fb.sputn(L"ef", 2); VERIFY( n == 2 ); @@ -58,8 +58,16 @@ void test01() VERIFY( !wmemcmp(buf, L"abcef", 5) ); fb.pubseekoff(0, ios_base::beg); - n = fb.sputn(L"ghijkl", 6); - VERIFY( n == 6 ); + n = fb.sputn(L"gh", 2); + VERIFY( n == 2 ); + + // Check write => read without pubseekoff(0, ios_base::cur) + + n = fb.sgetn( buf, 3 ); + VERIFY( !memcmp(buf, L"cef", 3) ); + + n = fb.sputn(L"ijkl", 4); + VERIFY( n == 4 ); fb.pubseekoff(0, ios_base::beg); n = fb.sgetn(buf, 2); @@ -72,8 +80,8 @@ void test01() fb.pubseekoff(0, ios_base::beg); n = fb.sgetn(buf, size); - VERIFY( n == 9 ); - VERIFY( !wmemcmp(buf, L"ghijklmno", 9) ); + VERIFY( n == 12 ); + VERIFY( !wmemcmp(buf, L"ghcefijklmno", 12) ); fb.close(); } diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc deleted file mode 100644 index a64f4558d9f..00000000000 --- a/libstdc++-v3/testsuite/27_io/basic_filebuf/sync/wchar_t/1.cc +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2003, 2009 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 3, 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 COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -// 27.8.1.4 Overridden virtual functions - -#include <fstream> -#include <testsuite_hooks.h> - -void test01() -{ - using namespace std; - - bool test __attribute__((unused)) = true; - const char* name = "tmp_sync_1"; - - wfilebuf fb; - - fb.open(name, ios_base::in | ios_base::out | ios_base::trunc); - fb.sputn(L"abc", 3); - - fb.pubseekoff(0, ios_base::beg); - fb.sputc(L'1'); - - // Sync can't be used to switch from write mode to read mode. - fb.pubsync(); - - wfilebuf::int_type c = fb.sbumpc(); - VERIFY( c == wfilebuf::traits_type::eof() ); - - fb.close(); -} - -int main() -{ - test01(); - return 0; -} diff --git a/libstdc++-v3/testsuite/util/testsuite_character.h b/libstdc++-v3/testsuite/util/testsuite_character.h index 35ccfa89261..ceda1f5125e 100644 --- a/libstdc++-v3/testsuite/util/testsuite_character.h +++ b/libstdc++-v3/testsuite/util/testsuite_character.h @@ -294,7 +294,7 @@ namespace std const extern_type* end, size_t max) const { const extern_type* beg = from; - while (from < end && max) + while (from < end) { unsigned char c = *from; if (c & 0xc0) @@ -304,6 +304,8 @@ namespace std ++from; continue; } + + if (max == 0) break; unsigned char tmp; if (state.value & 0x8) |