diff options
77 files changed, 1728 insertions, 177 deletions
diff --git a/ChangeLog.melt b/ChangeLog.melt index 58e2d028b23..e5ee3dd83ea 100644 --- a/ChangeLog.melt +++ b/ChangeLog.melt @@ -1,3 +1,6 @@ +2008-06-03 Basile Starynkevitch <basile@starynkevitch.net> + MELT branch merged with trunk r136317 + 2008-06-02 Basile Starynkevitch <basile@starynkevitch.net> MELT branch merged with trunk r136272 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cd13a87e68f..b42de54c2c4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,121 @@ +2008-06-03 Richard Guenther <rguenther@suse.de> + + * tree-ssa-structalias.c (find_func_aliases): Add constraints + for the lhs of calls if the return type contains pointers. + +2008-06-03 Kai Tietz <kai.tietz@onevision.com> + + * doc/tm.texi (OVERRIDE_ABI_FORMAT): New. + * doc/extend.texi (ms_abi,sysv_abi): New attribute description. + * function.c (allocate_struct_function): Use of + OVERRIDE_ABI_FORMAT. + * config/i386/cygming.h (TARGET_64BIT_MS_ABI): Make use + of cfun and DEFAULT_ABI to deceide abi mode. + (DEFAULT_ABI): New. + (REG_PARM_STACK_SPACE): Removed. + (OUTGOING_REG_PARM_STACK_SPACE): Removed. + (STACK_BOUNDARY): Use default target to deceide stack boundary. + * config/i386/i386-protos.h (ix86_cfun_abi): New. + (ix86_function_abi): Likewise. + (ix86_function_type_abi): Likewise. + (ix86_call_abi_override): Likewise. + * confid/i386/i386.md (SSE_REGPARM_MAX): Replaced by abi + specific define X86_64_SSE_REGPARM_MAX/X64_SSE_REGPARM_MAX. + * config/i386/i386.c (override_options): Replace TARGET_64BIT_MS_ABI. + (X86_64_VARARGS_SIZE): Replace REGPARM_MAX and SSE_REGPARM_MAX by abi + specific defines. + (X86_64_REGPARM_MAX): New. + (X86_64_SSE_REGPARM_MAX): New. + (X64_REGPARM_MAX): New. + (X64_SSE_REGPARM_MAX): New. + (X86_32_REGPARM_MAX): New. + (X86_32_SSE_REGPARM_MAX): New. + (ix86_handle_cconv_attribute): Replace TARGET_64BIT_MS_ABI. + (ix86_function_regparm): Handle user calling abi. + (ix86_function_arg_regno_p): Replace TARGET_64BIT_MS_ABI + by DEFAULT_ABI versus SYSV_ABI check. + (ix86_reg_parm_stack_space): New. + (ix86_function_type_abi): New. + (ix86_call_abi_override): New. + (ix86_function_abi): New. + (ix86_cfun_abi): New. + (init_cumulative_args): Call abi specific initialization. + (function_arg_advance): Remove TARGET_64BIT_MS_ABI. + (function_arg_64): Extend SSE_REGPARM_MAX check. + (function_arg (): Remove TARGET_64BIT_MS_ABI. + (ix86_pass_by_reference): Likewise. + (ix86_function_value_regno_p): Likewise. + (function_value_64): Replace REGPARM_MAX, and SSE_REGPARM_MAX. + (ix86_function_value_1): Replace TARGET_64BIT_MS_ABI. + (return_in_memory_ms_64): Replace TARGET_64BIT_MS_ABI. + (ix86_build_builtin_va_list): Replace TARGET_64BIT_MS_ABI. + (setup_incoming_varargs_64): Adjust regparm for call abi. + (ix86_setup_incoming_varargs): Replace TARGET_64BIT_MS_ABI. + (ix86_va_start): Likewise. + (ix86_gimplify_va_arg): Likewise. + (ix86_expand_prologue): Likewise. + (output_pic_addr_const): Likewise. + (ix86_init_machine_status): Initialize call_abi by DEFAULT_ABI. + (x86_this_parameter): Replace TARGET_64BIT_MS_ABI. + (x86_output_mi_thunk): Likewise. + (x86_function_profiler): Likewise. + * config/i386/i386.h (TARGET_64BIT_MS_ABI): Use ix64_cfun_abi. + (SYSV_ABI, MS_ABI): New constants. + (DEFAULT_ABI): New. + (init_regs): Add prototype of function in regclass.c file. + (OVERRIDE_ABI_FORMAT): New. + (CONDITIONAL_REGISTER_USAGE): Remove TARGET_64BIT_MS_ABI part. + (REG_PARM_STACK_SPACE): Use ix86_reg_parm_stack_space. + (OUTGOING_REG_PARM_STACK_SPACE): New. + (ix86_reg_parm_stack_space): New prototype. + (CUMULATIVE_ARGS): Add call_abi member. + (machine_function): Add call_abi member. + * config/i386/mingw32.h (EXTRA_OS_CPP_BUILTINS): Replace TARGET_64BIT_MS_ABI + by DEFAULT_ABI compare to MS_ABI. + +2008-06-02 Andy Hutchinson <hutchinsonandy@aim.com> + + PR target/34879 + * config/avr/avr.c (TARGET_BUILTIN_SETJMP_FRAME_VALUE): Redefine. + (avr_builtin_setjmp_frame_value): New function. + * config/avr/avr.md (nonlocal_goto_receiver): Define. + (nonlocal_goto): Define. + +2008-06-02 Richard Sandiford <rdsandiford@googlemail.com> + + * config/mips/mips.c (mips_emit_loadgp): Return early if + there is nothing do to, otherwise emit a blockage if + !TARGET_EXPLICIT_RELOCS || crtl->profile. + * config/mips/mips.md (loadgp_blockage): Use SI rather than DI. + +2008-06-02 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * configure.ac: Drop unneeded backslash ending up in config.in. + * acinclude.m4: Likewise. + * config.in: Regenerate. + +2008-05-26 Jan Hubicka <jh@suse.cz> + + * predict.c (maybe_hot_frequency_p): Break out of... + (maybe_hot_bb_p): ... here. + (maybe_hot_edge_p): New. + * tree-ssa-coalesce.c (coalesce_cost_edge): Compute cost based on edge. + * basic-block.h (maybe_hot_edge_p): Declare. + +2008-05-31 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.md (*cmpfp_<mode>): Enable for optimize_size. + (*cmpfp_<mode>_cc): Ditto. + (*fp_jcc_8<mode>_387): Ditto. + (*fop_<MODEF:mode>_2_i387): Ditto. + (*fop_<MODEF:mode>_3_i387): Ditto. + (*fop_xf_2_i387): Ditto. + (*fop_xf_3_i387): Ditto. + +2008-06-02 Tomas Bily <tbily@suse.cz> + + * tree-ssa-ifcombine.c (get_name_for_bit_test): Use CONVERT_EXPR_P. + 2008-06-01 Richard Sandiford <rdsandiford@googlemail.com> * config/mips/mips.c (mips_valid_offset_p): New function. @@ -112,14 +230,14 @@ Revert 2007-11-29 Zdenek Dvorak <ook@ucw.cz> - PR tree-optimization/34244 - * tree-vrp.c (adjust_range_with_scev): Clear scev cache. - (record_numbers_of_iterations): New function. - (execute_vrp): Cache the numbers of iterations of loops. - * tree-scalar-evolution.c (scev_reset_except_niters): - New function. - (scev_reset): Use scev_reset_except_niters. - * tree-scalar-evolution.h (scev_reset_except_niters): Declare. + PR tree-optimization/34244 + * tree-vrp.c (adjust_range_with_scev): Clear scev cache. + (record_numbers_of_iterations): New function. + (execute_vrp): Cache the numbers of iterations of loops. + * tree-scalar-evolution.c (scev_reset_except_niters): + New function. + (scev_reset): Use scev_reset_except_niters. + * tree-scalar-evolution.h (scev_reset_except_niters): Declare. 2008-05-31 Bernd Schmidt <bernd.schmidt@analog.com> diff --git a/gcc/ChangeLog.melt b/gcc/ChangeLog.melt index a2d377192b8..ecafc018dff 100644 --- a/gcc/ChangeLog.melt +++ b/gcc/ChangeLog.melt @@ -1,4 +1,7 @@ 2008-06-03 Basile Starynkevitch <basile@starynkevitch.net> + MELT branch merged with trunk r136317 + +2008-06-03 Basile Starynkevitch <basile@starynkevitch.net> * melt/warm-basilys.bysl: using debug_msg macro everywhere instead of debugmsg. * warm-basilys-0.c: regenerated. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 5b3d552a6f1..e58334c1e1f 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20080602 +20080603 diff --git a/gcc/acinclude.m4 b/gcc/acinclude.m4 index 70322c75e6b..9f865ee28d4 100644 --- a/gcc/acinclude.m4 +++ b/gcc/acinclude.m4 @@ -347,7 +347,7 @@ if test $gcc_cv_c_nbby = failed; then AC_MSG_ERROR(cannot determine number of bits in a byte) else AC_DEFINE_UNQUOTED(CHAR_BIT, $gcc_cv_c_nbby, - [Define as the number of bits in a byte, if \`limits.h' doesn't.]) + [Define as the number of bits in a byte, if `limits.h' doesn't.]) fi fi]) diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 97f178b5315..116e9521626 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -841,6 +841,7 @@ extern void compute_available (sbitmap *, sbitmap *, sbitmap *, sbitmap *); /* In predict.c */ extern bool maybe_hot_bb_p (const_basic_block); +extern bool maybe_hot_edge_p (edge); extern bool probably_cold_bb_p (const_basic_block); extern bool probably_never_executed_bb_p (const_basic_block); extern bool tree_predicted_by_p (const_basic_block, enum br_predictor); diff --git a/gcc/config.in b/gcc/config.in index 838fdd90c90..b2b5ba49685 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1,6 +1,6 @@ /* config.in. Generated from configure.ac by autoheader. */ -/* Define as the number of bits in a byte, if \`limits.h' doesn't. */ +/* Define as the number of bits in a byte, if `limits.h' doesn't. */ #ifndef USED_FOR_TARGET #undef CHAR_BIT #endif @@ -1560,7 +1560,7 @@ #endif -/* Define to \`long' if <sys/resource.h> doesn't define. */ +/* Define to `long' if <sys/resource.h> doesn't define. */ #ifndef USED_FOR_TARGET #undef rlim_t #endif diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 7135c79610a..405f42f7632 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -83,6 +83,8 @@ static bool avr_rtx_costs (rtx, int, int, int *); static int avr_address_cost (rtx); static bool avr_return_in_memory (const_tree, const_tree); static struct machine_function * avr_init_machine_status (void); +static rtx avr_builtin_setjmp_frame_value (void); + /* Allocate registers from r25 to r8 for parameters for function calls. */ #define FIRST_CUM_REG 26 @@ -323,6 +325,9 @@ int avr_case_values_threshold = 30000; #undef TARGET_STRICT_ARGUMENT_NAMING #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true +#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE +#define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value + struct gcc_target targetm = TARGET_INITIALIZER; void @@ -523,6 +528,17 @@ initial_elimination_offset (int from, int to) } } +/* Actual start of frame is virtual_stack_vars_rtx this is offset from + frame pointer by +STARTING_FRAME_OFFSET. + Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET + avoids creating add/sub of offset in nonlocal goto and setjmp. */ + +rtx avr_builtin_setjmp_frame_value (void) +{ + return gen_rtx_MINUS (Pmode, virtual_stack_vars_rtx, + gen_int_mode (STARTING_FRAME_OFFSET, Pmode)); +} + /* Return 1 if the function epilogue is just a single "ret". */ int diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index a4914c4aa61..0fd371282cc 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -58,7 +58,8 @@ (UNSPECV_PROLOGUE_SAVES 0) (UNSPECV_EPILOGUE_RESTORES 1) (UNSPECV_WRITE_SP_IRQ_ON 2) - (UNSPECV_WRITE_SP_IRQ_OFF 3)]) + (UNSPECV_WRITE_SP_IRQ_OFF 3) + (UNSPECV_GOTO_RECEIVER 4)]) (include "predicates.md") (include "constraints.md") @@ -115,6 +116,63 @@ (const_int 2))] (const_int 2))) +;;======================================================================== +;; The following is used by nonlocal_goto and setjmp. +;; The receiver pattern will create no instructions since internally +;; virtual_stack_vars = hard_frame_pointer + 1 so the RTL become R28=R28 +;; This avoids creating add/sub offsets in frame_pointer save/resore. +;; The 'null' receiver also avoids problems with optimisation +;; not recognising incoming jmp and removing code that resets frame_pointer. +;; The code derived from builtins.c. + +(define_expand "nonlocal_goto_receiver" + [(set (reg:HI REG_Y) + (unspec_volatile:HI [(const_int 0)] UNSPECV_GOTO_RECEIVER))] + "" + { + emit_move_insn (virtual_stack_vars_rtx, + gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, + gen_int_mode (STARTING_FRAME_OFFSET, + Pmode))); + /* This might change the hard frame pointer in ways that aren't + apparent to early optimization passes, so force a clobber. */ + emit_clobber (hard_frame_pointer_rtx); + DONE; + }) + + +;; Defining nonlocal_goto_receiver means we must also define this. +;; even though its function is identical to that in builtins.c + +(define_expand "nonlocal_goto" + [ + (use (match_operand 0 "general_operand")) + (use (match_operand 1 "general_operand")) + (use (match_operand 2 "general_operand")) + (use (match_operand 3 "general_operand")) + ] + "" +{ + rtx r_label = copy_to_reg (operands[1]); + rtx r_fp = operands[3]; + rtx r_sp = operands[2]; + + emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))); + + emit_clobber (gen_rtx_MEM (BLKmode, hard_frame_pointer_rtx)); + + emit_move_insn (hard_frame_pointer_rtx, r_fp); + emit_stack_restore (SAVE_NONLOCAL, r_sp, NULL_RTX); + + emit_use (hard_frame_pointer_rtx); + emit_use (stack_pointer_rtx); + + emit_indirect_jump (r_label); + + DONE; +}) + + (define_insn "*pushqi" [(set (mem:QI (post_dec (reg:HI REG_SP))) (match_operand:QI 0 "reg_or_0_operand" "r,L"))] diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h index bf46cab15f7..1070c85e71d 100644 --- a/gcc/config/i386/cygming.h +++ b/gcc/config/i386/cygming.h @@ -34,7 +34,10 @@ along with GCC; see the file COPYING3. If not see #endif #undef TARGET_64BIT_MS_ABI -#define TARGET_64BIT_MS_ABI TARGET_64BIT +#define TARGET_64BIT_MS_ABI (!cfun ? DEFAULT_ABI == MS_ABI : TARGET_64BIT && cfun->machine->call_abi == MS_ABI) + +#undef DEFAULT_ABI +#define DEFAULT_ABI (TARGET_64BIT ? MS_ABI : SYSV_ABI) #undef DBX_REGISTER_NUMBER #define DBX_REGISTER_NUMBER(n) \ @@ -123,18 +126,6 @@ along with GCC; see the file COPYING3. If not see #undef LONG_TYPE_SIZE #define LONG_TYPE_SIZE 32 -#undef REG_PARM_STACK_SPACE -#define REG_PARM_STACK_SPACE(FNDECL) (TARGET_64BIT_MS_ABI ? 32 : 0) - -#undef OUTGOING_REG_PARM_STACK_SPACE -#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) (TARGET_64BIT_MS_ABI ? 1 : 0) - -#undef REGPARM_MAX -#define REGPARM_MAX (TARGET_64BIT_MS_ABI ? 4 : 3) - -#undef SSE_REGPARM_MAX -#define SSE_REGPARM_MAX (TARGET_64BIT_MS_ABI ? 4 : TARGET_SSE ? 3 : 0) - /* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */ #define HANDLE_PRAGMA_PACK_PUSH_POP 1 /* Enable push_macro & pop_macro */ @@ -214,7 +205,7 @@ do { \ #define CHECK_STACK_LIMIT 4000 #undef STACK_BOUNDARY -#define STACK_BOUNDARY (TARGET_64BIT_MS_ABI ? 128 : BITS_PER_WORD) +#define STACK_BOUNDARY (DEFAULT_ABI == MS_ABI ? 128 : BITS_PER_WORD) /* By default, target has a 80387, uses IEEE compatible arithmetic, returns float values in the 387 and needs stack probes. diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 6fdea06c518..a92272bdb38 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -137,6 +137,11 @@ extern int ix86_function_arg_boundary (enum machine_mode, tree); extern bool ix86_sol10_return_in_memory (const_tree,const_tree); extern rtx ix86_force_to_memory (enum machine_mode, rtx); extern void ix86_free_from_memory (enum machine_mode); +extern int ix86_cfun_abi (void); +extern int ix86_function_abi (const_tree); +extern int ix86_function_type_abi (const_tree); +extern void ix86_call_abi_override (const_tree); + extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx, rtx, rtx, rtx, rtx); extern bool ix86_hard_regno_mode_ok (int, enum machine_mode); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 16e74228ddf..b159ce42928 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1619,7 +1619,7 @@ rtx ix86_compare_op1 = NULL_RTX; rtx ix86_compare_emitted = NULL_RTX; /* Size of the register save area. */ -#define X86_64_VARARGS_SIZE (REGPARM_MAX * UNITS_PER_WORD + SSE_REGPARM_MAX * 16) +#define X86_64_VARARGS_SIZE (X86_64_REGPARM_MAX * UNITS_PER_WORD + X86_64_SSE_REGPARM_MAX * 16) /* Define the structure for the machine field in struct function. */ @@ -2306,11 +2306,11 @@ override_options (void) } else { - /* For TARGET_64BIT_MS_ABI, force pic on, in order to enable the + /* For TARGET_64BIT and MS_ABI, force pic on, in order to enable the use of rip-relative addressing. This eliminates fixups that would otherwise be needed if this object is to be placed in a DLL, and is essentially just as efficient as direct addressing. */ - if (TARGET_64BIT_MS_ABI) + if (TARGET_64BIT && DEFAULT_ABI == MS_ABI) ix86_cmodel = CM_SMALL_PIC, flag_pic = 1; else if (TARGET_64BIT) ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL; @@ -2761,8 +2761,9 @@ override_options (void) set_param_value ("l2-cache-size", ix86_cost->l2_cache_size); /* If using typedef char *va_list, signal that __builtin_va_start (&ap, 0) - can be optimized to ap = __builtin_next_arg (0). */ - if (!TARGET_64BIT || TARGET_64BIT_MS_ABI) + can be optimized to ap = __builtin_next_arg (0). + For abi switching it should be corrected. */ + if (!TARGET_64BIT || DEFAULT_ABI == MS_ABI) targetm.expand_builtin_va_start = NULL; #ifdef USE_IX86_CLD @@ -3166,7 +3167,7 @@ ix86_handle_cconv_attribute (tree *node, tree name, if (TARGET_64BIT) { /* Do not warn when emulating the MS ABI. */ - if (!TARGET_64BIT_MS_ABI) + if (TREE_CODE (*node) != FUNCTION_TYPE || !ix86_function_type_abi (*node)) warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name)); *no_add_attrs = true; @@ -3269,7 +3270,11 @@ ix86_function_regparm (const_tree type, const_tree decl) static bool error_issued; if (TARGET_64BIT) - return regparm; + { + if (ix86_function_type_abi (type) == DEFAULT_ABI) + return regparm; + return DEFAULT_ABI != SYSV_ABI ? X86_64_REGPARM_MAX : X64_REGPARM_MAX; + } attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type)); if (attr) @@ -3500,15 +3505,20 @@ ix86_function_arg_regno_p (int regno) return true; } + /* TODO: The function should depend on current function ABI but + builtins.c would need updating then. Therefore we use the + default ABI. */ + /* RAX is used as hidden argument to va_arg functions. */ - if (!TARGET_64BIT_MS_ABI && regno == AX_REG) + if (DEFAULT_ABI == SYSV_ABI && regno == AX_REG) return true; - if (TARGET_64BIT_MS_ABI) + if (DEFAULT_ABI == MS_ABI) parm_regs = x86_64_ms_abi_int_parameter_registers; else parm_regs = x86_64_int_parameter_registers; - for (i = 0; i < REGPARM_MAX; i++) + for (i = 0; i < (DEFAULT_ABI == MS_ABI ? X64_REGPARM_MAX + : X86_64_REGPARM_MAX); i++) if (regno == parm_regs[i]) return true; return false; @@ -3529,6 +3539,98 @@ ix86_must_pass_in_stack (enum machine_mode mode, const_tree type) && type && TREE_CODE (type) != VECTOR_TYPE); } +/* It returns the size, in bytes, of the area reserved for arguments passed + in registers for the function represented by fndecl dependent to the used + abi format. */ +unsigned int +ix86_reg_parm_stack_space (const_tree fndecl) +{ + int call_abi = 0; + /* For libcalls it is possible that there is no fndecl at hand. + Therefore assume for this case the default abi of the target. */ + if (!fndecl) + call_abi = DEFAULT_ABI; + else + call_abi = ix86_function_abi (fndecl); + if (call_abi == 1) + return 32; + return 0; +} + +/* Returns value SYSV_ABI, MS_ABI dependent on fntype, specifying the + call abi used. */ +int +ix86_function_type_abi (const_tree fntype) +{ + if (TARGET_64BIT && fntype != NULL) + { + int abi; + if (DEFAULT_ABI == SYSV_ABI) + abi = lookup_attribute ("ms_abi", TYPE_ATTRIBUTES (fntype)) ? MS_ABI : SYSV_ABI; + else + abi = lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (fntype)) ? SYSV_ABI : MS_ABI; + + if (DEFAULT_ABI == MS_ABI && abi == SYSV_ABI) + sorry ("using sysv calling convention on target w64 is not supported"); + + return abi; + } + return DEFAULT_ABI; +} + +int +ix86_function_abi (const_tree fndecl) +{ + if (! fndecl) + return DEFAULT_ABI; + return ix86_function_type_abi (TREE_TYPE (fndecl)); +} + +/* Returns value SYSV_ABI, MS_ABI dependent on cfun, specifying the + call abi used. */ +int +ix86_cfun_abi (void) +{ + if (! cfun || ! TARGET_64BIT) + return DEFAULT_ABI; + return cfun->machine->call_abi; +} + +/* regclass.c */ +extern void init_regs (void); + +/* Implementation of call abi switching target hook. Specific to FNDECL + the specific call register sets are set. See also CONDITIONAL_REGISTER_USAGE + for more details. + To prevent redudant calls of costy function init_regs (), it checks not to + reset register usage for default abi. */ +void +ix86_call_abi_override (const_tree fndecl) +{ + if (fndecl == NULL_TREE) + cfun->machine->call_abi = DEFAULT_ABI; + else + cfun->machine->call_abi = ix86_function_type_abi (TREE_TYPE (fndecl)); + if (TARGET_64BIT && cfun->machine->call_abi == MS_ABI && call_used_regs) + { + if (call_used_regs[4 /*RSI*/] != 0 || call_used_regs[5 /*RDI*/] != 0) + { + call_used_regs[4 /*RSI*/] = 0; + call_used_regs[5 /*RDI*/] = 0; + init_regs (); + } + } + else if (TARGET_64BIT && call_used_regs) + { + if (call_used_regs[4 /*RSI*/] != 1 || call_used_regs[5 /*RDI*/] != 1) + { + call_used_regs[4 /*RSI*/] = 1; + call_used_regs[5 /*RDI*/] = 1; + init_regs (); + } + } +} + /* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. */ @@ -3542,10 +3644,25 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ struct cgraph_local_info *i = fndecl ? cgraph_local_info (fndecl) : NULL; memset (cum, 0, sizeof (*cum)); + cum->call_abi = ix86_function_type_abi (fntype); /* Set up the number of registers to use for passing arguments. */ cum->nregs = ix86_regparm; + if (TARGET_64BIT) + { + if (cum->call_abi != DEFAULT_ABI) + cum->nregs = DEFAULT_ABI != SYSV_ABI ? X86_64_REGPARM_MAX + : X64_REGPARM_MAX; + } if (TARGET_SSE) - cum->sse_nregs = SSE_REGPARM_MAX; + { + cum->sse_nregs = SSE_REGPARM_MAX; + if (TARGET_64BIT) + { + if (cum->call_abi != DEFAULT_ABI) + cum->sse_nregs = DEFAULT_ABI != SYSV_ABI ? X86_64_SSE_REGPARM_MAX + : X64_SSE_REGPARM_MAX; + } + } if (TARGET_MMX) cum->mmx_nregs = MMX_REGPARM_MAX; cum->warn_sse = true; @@ -4331,7 +4448,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, if (type) mode = type_natural_mode (type); - if (TARGET_64BIT_MS_ABI) + if (TARGET_64BIT && (cum ? cum->call_abi : DEFAULT_ABI) == MS_ABI) function_arg_advance_ms_64 (cum, bytes, words); else if (TARGET_64BIT) function_arg_advance_64 (cum, mode, type, words); @@ -4458,8 +4575,11 @@ function_arg_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode, if (mode == VOIDmode) return GEN_INT (cum->maybe_vaarg ? (cum->sse_nregs < 0 - ? SSE_REGPARM_MAX - : cum->sse_regno) + ? (cum->call_abi == DEFAULT_ABI + ? SSE_REGPARM_MAX + : (DEFAULT_ABI != SYSV_ABI ? X86_64_SSE_REGPARM_MAX + : X64_SSE_REGPARM_MAX)) + : cum->sse_regno) : -1); return construct_container (mode, orig_mode, type, 0, cum->nregs, @@ -4533,7 +4653,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode omode, if (type && TREE_CODE (type) == VECTOR_TYPE) mode = type_natural_mode (type); - if (TARGET_64BIT_MS_ABI) + if (TARGET_64BIT && (cum ? cum->call_abi : DEFAULT_ABI) == MS_ABI) return function_arg_ms_64 (cum, mode, omode, named, bytes); else if (TARGET_64BIT) return function_arg_64 (cum, mode, omode, type); @@ -4553,7 +4673,7 @@ ix86_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, const_tree type, bool named ATTRIBUTE_UNUSED) { /* See Windows x64 Software Convention. */ - if (TARGET_64BIT_MS_ABI) + if (TARGET_64BIT && (cum ? cum->call_abi : DEFAULT_ABI) == MS_ABI) { int msize = (int) GET_MODE_SIZE (mode); if (type) @@ -4686,7 +4806,10 @@ ix86_function_value_regno_p (int regno) return true; case FIRST_FLOAT_REG: - if (TARGET_64BIT_MS_ABI) + /* TODO: The function should depend on current function ABI but + builtins.c would need updating then. Therefore we use the + default ABI. */ + if (TARGET_64BIT && DEFAULT_ABI == MS_ABI) return false; return TARGET_FLOAT_RETURNS_IN_80387; @@ -4777,7 +4900,7 @@ function_value_64 (enum machine_mode orig_mode, enum machine_mode mode, } ret = construct_container (mode, orig_mode, valtype, 1, - REGPARM_MAX, SSE_REGPARM_MAX, + X86_64_REGPARM_MAX, X86_64_SSE_REGPARM_MAX, x86_64_int_return_registers, 0); /* For zero sized structures, construct_container returns NULL, but we @@ -4825,7 +4948,7 @@ ix86_function_value_1 (const_tree valtype, const_tree fntype_or_decl, fn = fntype_or_decl; fntype = fn ? TREE_TYPE (fn) : fntype_or_decl; - if (TARGET_64BIT_MS_ABI) + if (TARGET_64BIT && ix86_function_type_abi (fntype) == MS_ABI) return function_value_ms_64 (orig_mode, mode); else if (TARGET_64BIT) return function_value_64 (orig_mode, mode, valtype); @@ -5022,7 +5145,7 @@ ix86_build_builtin_va_list (void) tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl; /* For i386 we use plain pointer to argument area. */ - if (!TARGET_64BIT || TARGET_64BIT_MS_ABI) + if (!TARGET_64BIT || ix86_cfun_abi () == MS_ABI) return build_pointer_type (char_type_node); record = (*lang_hooks.types.make_type) (RECORD_TYPE); @@ -5070,6 +5193,10 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum) rtx nsse_reg; alias_set_type set; int i; + int regparm = ix86_regparm; + + if((cum ? cum->call_abi : ix86_cfun_abi ()) != DEFAULT_ABI) + regparm = DEFAULT_ABI != SYSV_ABI ? X86_64_REGPARM_MAX : X64_REGPARM_MAX; if (! cfun->va_list_gpr_size && ! cfun->va_list_fpr_size) return; @@ -5089,7 +5216,7 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum) set = get_varargs_alias_set (); for (i = cum->regno; - i < ix86_regparm + i < regparm && i < cum->regno + cfun->va_list_gpr_size / UNITS_PER_WORD; i++) { @@ -5136,7 +5263,7 @@ setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum) tmp_reg = gen_reg_rtx (Pmode); emit_insn (gen_rtx_SET (VOIDmode, tmp_reg, plus_constant (save_area, - 8 * REGPARM_MAX + 127))); + 8 * X86_64_REGPARM_MAX + 127))); mem = gen_rtx_MEM (BLKmode, plus_constant (tmp_reg, -127)); MEM_NOTRAP_P (mem) = 1; set_mem_alias_set (mem, set); @@ -5154,7 +5281,7 @@ setup_incoming_varargs_ms_64 (CUMULATIVE_ARGS *cum) alias_set_type set = get_varargs_alias_set (); int i; - for (i = cum->regno; i < REGPARM_MAX; i++) + for (i = cum->regno; i < X64_REGPARM_MAX; i++) { rtx reg, mem; @@ -5192,7 +5319,7 @@ ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, if (stdarg_p (fntype)) function_arg_advance (&next_cum, mode, type, 1); - if (TARGET_64BIT_MS_ABI) + if ((cum ? cum->call_abi : DEFAULT_ABI) == MS_ABI) setup_incoming_varargs_ms_64 (&next_cum); else setup_incoming_varargs_64 (&next_cum); @@ -5209,7 +5336,7 @@ ix86_va_start (tree valist, rtx nextarg) tree type; /* Only 64bit target needs something special. */ - if (!TARGET_64BIT || TARGET_64BIT_MS_ABI) + if (!TARGET_64BIT || cfun->machine->call_abi == MS_ABI) { std_expand_builtin_va_start (valist, nextarg); return; @@ -5244,7 +5371,7 @@ ix86_va_start (tree valist, rtx nextarg) { type = TREE_TYPE (fpr); t = build2 (GIMPLE_MODIFY_STMT, type, fpr, - build_int_cst (type, n_fpr * 16 + 8*REGPARM_MAX)); + build_int_cst (type, n_fpr * 16 + 8*X86_64_REGPARM_MAX)); TREE_SIDE_EFFECTS (t) = 1; expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); } @@ -5288,7 +5415,7 @@ ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) enum machine_mode nat_mode; /* Only 64bit target needs something special. */ - if (!TARGET_64BIT || TARGET_64BIT_MS_ABI) + if (!TARGET_64BIT || cfun->machine->call_abi == MS_ABI) return std_gimplify_va_arg_expr (valist, type, pre_p, post_p); f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); @@ -5310,7 +5437,8 @@ ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) nat_mode = type_natural_mode (type); container = construct_container (nat_mode, TYPE_MODE (type), type, 0, - REGPARM_MAX, SSE_REGPARM_MAX, intreg, 0); + X86_64_REGPARM_MAX, X86_64_SSE_REGPARM_MAX, + intreg, 0); /* Pull the value out of the saved registers. */ @@ -5379,7 +5507,7 @@ ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) if (needed_intregs) { t = build_int_cst (TREE_TYPE (gpr), - (REGPARM_MAX - needed_intregs + 1) * 8); + (X86_64_REGPARM_MAX - needed_intregs + 1) * 8); t = build2 (GE_EXPR, boolean_type_node, gpr, t); t2 = build1 (GOTO_EXPR, void_type_node, lab_false); t = build3 (COND_EXPR, void_type_node, t, t2, NULL_TREE); @@ -5388,8 +5516,8 @@ ix86_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) if (needed_sseregs) { t = build_int_cst (TREE_TYPE (fpr), - (SSE_REGPARM_MAX - needed_sseregs + 1) * 16 - + REGPARM_MAX * 8); + (X86_64_SSE_REGPARM_MAX - needed_sseregs + 1) * 16 + + X86_64_REGPARM_MAX * 8); t = build2 (GE_EXPR, boolean_type_node, fpr, t); t2 = build1 (GOTO_EXPR, void_type_node, lab_false); t = build3 (COND_EXPR, void_type_node, t, t2, NULL_TREE); @@ -6515,9 +6643,9 @@ ix86_expand_prologue (void) bool eax_live; rtx t; - gcc_assert (!TARGET_64BIT || TARGET_64BIT_MS_ABI); + gcc_assert (!TARGET_64BIT || cfun->machine->call_abi == MS_ABI); - if (TARGET_64BIT_MS_ABI) + if (cfun->machine->call_abi == MS_ABI) eax_live = false; else eax_live = ix86_eax_live_at_start_p (); @@ -8331,7 +8459,7 @@ output_pic_addr_const (FILE *file, rtx x, int code) #endif assemble_name (file, name); } - if (!TARGET_MACHO && !TARGET_64BIT_MS_ABI + if (!TARGET_MACHO && !(TARGET_64BIT && DEFAULT_ABI == MS_ABI) && code == 'P' && ! SYMBOL_REF_LOCAL_P (x)) fputs ("@PLT", file); break; @@ -16422,6 +16550,7 @@ ix86_init_machine_status (void) f = GGC_CNEW (struct machine_function); f->use_fast_prologue_epilogue_nregs = -1; f->tls_descriptor_call_expanded_p = 0; + f->call_abi = DEFAULT_ABI; return f; } @@ -23009,7 +23138,7 @@ x86_this_parameter (tree function) { const int *parm_regs; - if (TARGET_64BIT_MS_ABI) + if (ix86_function_type_abi (type) == MS_ABI) parm_regs = x86_64_ms_abi_int_parameter_registers; else parm_regs = x86_64_int_parameter_registers; @@ -23177,7 +23306,7 @@ x86_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED, output_asm_insn ("jmp\t%P0", xops); /* All thunks should be in the same object as their target, and thus binds_local_p should be true. */ - else if (TARGET_64BIT_MS_ABI) + else if (TARGET_64BIT && cfun->machine->call_abi == MS_ABI) gcc_unreachable (); else { @@ -23259,7 +23388,7 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) fprintf (file, "\tleaq\t%sP%d@(%%rip),%%r11\n", LPREFIX, labelno); #endif - if (!TARGET_64BIT_MS_ABI && flag_pic) + if (DEFAULT_ABI == SYSV_ABI && flag_pic) fprintf (file, "\tcall\t*%s@GOTPCREL(%%rip)\n", MCOUNT_NAME); else fprintf (file, "\tcall\t%s\n", MCOUNT_NAME); diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index ef8da17af3f..552515fc6c3 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -446,7 +446,17 @@ extern tree x86_mfence; #define TARGET_MACHO 0 /* Likewise, for the Windows 64-bit ABI. */ -#define TARGET_64BIT_MS_ABI 0 +#define TARGET_64BIT_MS_ABI (TARGET_64BIT && ix86_cfun_abi () == MS_ABI) + +/* Available call abi. */ +enum +{ + SYSV_ABI = 0, + MS_ABI = 1 +}; + +/* The default abi form used by target. */ +#define DEFAULT_ABI SYSV_ABI /* Subtargets may reset this to 1 in order to enable 96-bit long double with the rounding mode forced to 53 bits. */ @@ -804,7 +814,8 @@ enum target_cpu_default #define PARM_BOUNDARY BITS_PER_WORD /* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY BITS_PER_WORD +#define STACK_BOUNDARY (TARGET_64BIT && DEFAULT_ABI == MS_ABI ? 128 \ + : BITS_PER_WORD) /* Boundary (in *bits*) on which the stack pointer prefers to be aligned; the compiler cannot rely on having this alignment. */ @@ -1044,6 +1055,8 @@ enum target_cpu_default #define ORDER_REGS_FOR_LOCAL_ALLOC x86_order_regs_for_local_alloc () +#define OVERRIDE_ABI_FORMAT(FNDECL) ix86_call_abi_override (FNDECL) + /* Macro to conditionally modify fixed_regs/call_used_regs. */ #define CONDITIONAL_REGISTER_USAGE \ do { \ @@ -1094,7 +1107,7 @@ do { \ for (i = FIRST_REX_SSE_REG; i <= LAST_REX_SSE_REG; i++) \ reg_names[i] = ""; \ } \ - if (TARGET_64BIT_MS_ABI) \ + if (TARGET_64BIT && DEFAULT_ABI == MS_ABI) \ { \ call_used_regs[4 /*RSI*/] = 0; \ call_used_regs[5 /*RDI*/] = 0; \ @@ -1624,7 +1637,11 @@ enum reg_class This space can be allocated by the caller, or be a part of the machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says which. */ -#define REG_PARM_STACK_SPACE(FNDECL) 0 +#define REG_PARM_STACK_SPACE(FNDECL) ix86_reg_parm_stack_space (FNDECL) + +#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) (ix86_function_type_abi (FNTYPE) == MS_ABI ? 1 : 0) + +extern unsigned int ix86_reg_parm_stack_space (const_tree); /* Value is the number of bytes of arguments automatically popped when returning from a subroutine call. @@ -1686,6 +1703,8 @@ typedef struct ix86_args { int maybe_vaarg; /* true for calls to possibly vardic fncts. */ int float_in_sse; /* 1 if in 32-bit mode SFmode (2 for DFmode) should be passed in SSE registers. Otherwise 0. */ + int call_abi; /* Set to SYSV_ABI for sysv abi. Otherwise + MS_ABI for ms abi. */ } CUMULATIVE_ARGS; /* Initialize a variable CUM of type CUMULATIVE_ARGS @@ -1953,9 +1972,22 @@ do { \ is also used as the pic register in ELF. So for now, don't allow more than 3 registers to be passed in registers. */ -#define REGPARM_MAX (TARGET_64BIT ? 6 : 3) +/* Abi specific values for REGPARM_MAX and SSE_REGPARM_MAX */ +#define X86_64_REGPARM_MAX 6 +#define X64_REGPARM_MAX 4 +#define X86_32_REGPARM_MAX 3 + +#define X86_64_SSE_REGPARM_MAX 8 +#define X64_SSE_REGPARM_MAX 4 +#define X86_32_SSE_REGPARM_MAX (TARGET_SSE ? 3 : 0) + +#define REGPARM_MAX (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? X64_REGPARM_MAX \ + : X86_64_REGPARM_MAX) \ + : X86_32_REGPARM_MAX) -#define SSE_REGPARM_MAX (TARGET_64BIT ? 8 : (TARGET_SSE ? 3 : 0)) +#define SSE_REGPARM_MAX (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? X64_SSE_REGPARM_MAX \ + : X86_64_SSE_REGPARM_MAX) \ + : X86_32_SSE_REGPARM_MAX) #define MMX_REGPARM_MAX (TARGET_64BIT ? 0 : (TARGET_MMX ? 3 : 0)) @@ -2464,6 +2496,9 @@ struct machine_function GTY(()) ix86_current_function_calls_tls_descriptor macro for a better approximation. */ int tls_descriptor_call_expanded_p; + /* This value is used for amd64 targets and specifies the current abi + to be used. MS_ABI means ms abi. Otherwise SYSV_ABI means sysv abi. */ + int call_abi; }; #define ix86_stack_locals (cfun->machine->stack_locals) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c245a49fd3f..ba438fee50f 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1169,7 +1169,7 @@ [(match_operand:X87MODEI12 2 "memory_operand" "m")]))] UNSPEC_FNSTSW))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) - && TARGET_USE_<MODE>MODE_FIOP + && (TARGET_USE_<MODE>MODE_FIOP || optimize_size) && (GET_MODE (operands [3]) == GET_MODE (operands[1]))" "* return output_fp_compare (insn, operands, 0, 0);" [(set_attr "type" "multi") @@ -1186,7 +1186,7 @@ (clobber (match_operand:HI 0 "register_operand" "=a"))] "X87_FLOAT_MODE_P (GET_MODE (operands[1])) && TARGET_SAHF && !TARGET_CMOVE - && TARGET_USE_<MODE>MODE_FIOP + && (TARGET_USE_<MODE>MODE_FIOP || optimize_size) && (GET_MODE (operands [3]) == GET_MODE (operands[1]))" "#" "&& reload_completed" @@ -14288,7 +14288,7 @@ (clobber (reg:CCFP FLAGS_REG)) (clobber (match_scratch:HI 5 "=a,a"))] "X87_FLOAT_MODE_P (GET_MODE (operands[3])) - && TARGET_USE_<MODE>MODE_FIOP + && (TARGET_USE_<MODE>MODE_FIOP || optimize_size) && GET_MODE (operands[1]) == GET_MODE (operands[3]) && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0]))) && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode @@ -14708,7 +14708,10 @@ ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387 ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL), - operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1), + operands[0], const0_rtx, + GEN_INT ((DEFAULT_ABI == SYSV_ABI ? X86_64_SSE_REGPARM_MAX + : X64_SSE_REGPARM_MAX) + - 1), NULL, 0); for (i = 0; i < XVECLEN (operands[2], 0); i++) @@ -15926,7 +15929,7 @@ (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) (match_operand:MODEF 2 "register_operand" "0,0")]))] "TARGET_80387 && !TARGET_SSE_MATH - && TARGET_USE_<X87MODEI12:MODE>MODE_FIOP" + && (TARGET_USE_<X87MODEI12:MODE>MODE_FIOP || optimize_size)" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:MODEF 3 "mult_operator" "") @@ -15945,7 +15948,7 @@ (float:MODEF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] "TARGET_80387 && !TARGET_SSE_MATH - && TARGET_USE_<X87MODEI12:MODE>MODE_FIOP" + && (TARGET_USE_<X87MODEI12:MODE>MODE_FIOP || optimize_size)" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:MODEF 3 "mult_operator" "") @@ -15960,7 +15963,8 @@ (define_insn "*fop_df_4_i387" [(set (match_operand:DF 0 "register_operand" "=f,f") (match_operator:DF 3 "binary_fp_operator" - [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) + [(float_extend:DF + (match_operand:SF 1 "nonimmediate_operand" "fm,0")) (match_operand:DF 2 "register_operand" "0,f")]))] "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH) && !(MEM_P (operands[1]) && MEM_P (operands[2]))" @@ -16046,7 +16050,7 @@ [(float:XF (match_operand:X87MODEI12 1 "nonimmediate_operand" "m,?r")) (match_operand:XF 2 "register_operand" "0,0")]))] - "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP" + "TARGET_80387 && (TARGET_USE_<MODE>MODE_FIOP || optimize_size)" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -16064,7 +16068,7 @@ [(match_operand:XF 1 "register_operand" "0,0") (float:XF (match_operand:X87MODEI12 2 "nonimmediate_operand" "m,?r"))]))] - "TARGET_80387 && TARGET_USE_<MODE>MODE_FIOP" + "TARGET_80387 && (TARGET_USE_<MODE>MODE_FIOP || optimize_size)" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -20845,14 +20849,14 @@ (use (match_operand:DI 2 "const_int_operand" "i")) (use (label_ref:DI (match_operand 3 "" "X")))] "TARGET_64BIT - && INTVAL (operands[4]) + SSE_REGPARM_MAX * 16 - 16 < 128 + && INTVAL (operands[4]) + X86_64_SSE_REGPARM_MAX * 16 - 16 < 128 && INTVAL (operands[4]) + INTVAL (operands[2]) * 16 >= -128" { int i; operands[0] = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, operands[0], operands[4])); output_asm_insn ("jmp\t%A1", operands); - for (i = SSE_REGPARM_MAX - 1; i >= INTVAL (operands[2]); i--) + for (i = X86_64_SSE_REGPARM_MAX - 1; i >= INTVAL (operands[2]); i--) { operands[4] = adjust_address (operands[0], DImode, i*16); operands[5] = gen_rtx_REG (TImode, SSE_REGNO (i)); diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h index 3a3b74cf8be..7628896bc6a 100644 --- a/gcc/config/i386/mingw32.h +++ b/gcc/config/i386/mingw32.h @@ -38,7 +38,7 @@ along with GCC; see the file COPYING3. If not see builtin_define_std ("WINNT"); \ builtin_define_with_int_value ("_INTEGRAL_MAX_BITS", \ TYPE_PRECISION (intmax_type_node));\ - if (TARGET_64BIT_MS_ABI) \ + if (TARGET_64BIT && DEFAULT_ABI == MS_ABI) \ { \ builtin_define ("__MINGW64__"); \ builtin_define_std ("WIN64"); \ diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 551159c9e94..41fc6d03009 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -8516,8 +8516,6 @@ mips_emit_loadgp (void) emit_insn (Pmode == SImode ? gen_loadgp_newabi_si (pic_reg, offset, incoming_address) : gen_loadgp_newabi_di (pic_reg, offset, incoming_address)); - if (!TARGET_EXPLICIT_RELOCS) - emit_insn (gen_loadgp_blockage ()); break; case LOADGP_RTP: @@ -8526,13 +8524,16 @@ mips_emit_loadgp (void) emit_insn (Pmode == SImode ? gen_loadgp_rtp_si (pic_reg, base, index) : gen_loadgp_rtp_di (pic_reg, base, index)); - if (!TARGET_EXPLICIT_RELOCS) - emit_insn (gen_loadgp_blockage ()); break; default: - break; + return; } + /* Emit a blockage if there are implicit uses of the GP register. + This includes profiled functions, because FUNCTION_PROFILE uses + a jal macro. */ + if (!TARGET_EXPLICIT_RELOCS || crtl->profile) + emit_insn (gen_loadgp_blockage ()); } /* Expand the "prologue" pattern. */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 3370d9958c8..29b8e703890 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -4350,12 +4350,11 @@ } [(set_attr "length" "8")]) -;; The use of gp is hidden when not using explicit relocations. ;; This blockage instruction prevents the gp load from being ;; scheduled after an implicit use of gp. It also prevents ;; the load from being deleted as dead. (define_insn "loadgp_blockage" - [(unspec_volatile [(reg:DI 28)] UNSPEC_BLOCKAGE)] + [(unspec_volatile [(reg:SI 28)] UNSPEC_BLOCKAGE)] "" "" [(set_attr "type" "ghost") diff --git a/gcc/configure.ac b/gcc/configure.ac index ea53ec96d60..18d45fdefb3 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -1322,7 +1322,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/resource.h> #endif ]], [[rlim_t l = 0;]])],[],[AC_DEFINE([rlim_t],[long], -[Define to \`long' if <sys/resource.h> doesn't define.])]) +[Define to `long' if <sys/resource.h> doesn't define.])]) # On AIX 5.2, <ldfcn.h> conflicts with <fcntl.h>, as both define incompatible # FREAD and FWRITE macros. Fortunately, for GCC's single usage of ldgetname diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f9b197144dc..54afddc9851 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2008-06-02 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/36404 + * pt.c (push_template_decl_real): Consistently return error_mark_node + on error. + +2008-06-02 Tomas Bily <tbily@suse.cz> + + * typeck.c (is_bitfield_expr_with_lowered_type): Use CASE_CONVERT. + (cp_build_unary_op): Likewise. + (cp_build_indirect_ref): Use CONVERT_EXPR_P. + (maybe_warn_about_returning_address_of_local): Likewise. + 2008-05-29 Paolo Carlini <paolo.carlini@oracle.com> PR c++/35243 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 95440c98023..4bb43addb74 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3791,7 +3791,10 @@ push_template_decl_real (tree decl, bool is_friend) member_template_p = true; if (TREE_CODE (decl) == TYPE_DECL && ANON_AGGRNAME_P (DECL_NAME (decl))) - error ("template class without a name"); + { + error ("template class without a name"); + return error_mark_node; + } else if (TREE_CODE (decl) == FUNCTION_DECL) { if (DECL_DESTRUCTOR_P (decl)) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index bf264ad2cc7..026e4469b7d 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1515,8 +1515,7 @@ is_bitfield_expr_with_lowered_type (const_tree exp) return DECL_BIT_FIELD_TYPE (field); } - case NOP_EXPR: - case CONVERT_EXPR: + CASE_CONVERT: if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp, 0))) == TYPE_MAIN_VARIANT (TREE_TYPE (exp))) return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); @@ -2449,8 +2448,7 @@ cp_build_indirect_ref (tree ptr, const char *errorstring, types. */ tree t = canonical_type_variant (TREE_TYPE (type)); - if (TREE_CODE (ptr) == CONVERT_EXPR - || TREE_CODE (ptr) == NOP_EXPR + if (CONVERT_EXPR_P (ptr) || TREE_CODE (ptr) == VIEW_CONVERT_EXPR) { /* If a warning is issued, mark it to avoid duplicates from @@ -4658,8 +4656,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, switch (TREE_CODE (arg)) { - case NOP_EXPR: - case CONVERT_EXPR: + CASE_CONVERT: case FLOAT_EXPR: case FIX_TRUNC_EXPR: /* Even if we're not being pedantic, we cannot allow this @@ -6854,9 +6851,8 @@ maybe_warn_about_returning_address_of_local (tree retval) { if (TREE_CODE (whats_returned) == COMPOUND_EXPR) whats_returned = TREE_OPERAND (whats_returned, 1); - else if (TREE_CODE (whats_returned) == CONVERT_EXPR - || TREE_CODE (whats_returned) == NON_LVALUE_EXPR - || TREE_CODE (whats_returned) == NOP_EXPR) + else if (CONVERT_EXPR_P (whats_returned) + || TREE_CODE (whats_returned) == NON_LVALUE_EXPR) whats_returned = TREE_OPERAND (whats_returned, 0); else break; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 103af2c4c51..86d15743b26 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2508,6 +2508,19 @@ instruction). Caveat: such addressing is by definition not position independent and hence this attribute must not be used for objects defined by shared libraries. +@item ms_abi/sysv_abi +@cindex @code{ms_abi} attribute +@cindex @code{sysv_abi} attribute + +On 64-bit x86_65-*-* targets, you can use an ABI attribute to indicate +which calling convention should be used for a function. The @code{ms_abi} +attribute tells the compiler to use the Microsoft ABI, while the +@code{sysv_abi} attribute tells the compiler to use the ABI used on +GNU/Linux and other systems. The default is to use the Microsoft ABI +when targeting Windows. On all other systems, the default is the AMD ABI. + +Note, This feature is currently sorried out for Windows targets trying to + @item naked @cindex function without a prologue/epilogue code Use this attribute on the ARM, AVR, IP2K and SPU ports to indicate that diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 3e4d2b7b5bf..d18bf2e00e9 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4055,6 +4055,15 @@ arguments are passed on the stack, there is no need to store anything in should not be empty, so use @code{int}. @end defmac +@defmac OVERRIDE_ABI_FORMAT (@var{fndecl}) +If defined, this macro is called before generating any code for a +function, but after the @var{cfun} descriptor for the function has been +created. The back end may use this macro to update @var{cfun} to +reflect an ABI other than that which would normally be used by default. +If the compiler is generating code for a compiler-generated function, +@var{fndecl} may be @code{NULL}. +@end defmac + @defmac INIT_CUMULATIVE_ARGS (@var{cum}, @var{fntype}, @var{libname}, @var{fndecl}, @var{n_named_args}) A C statement (sans semicolon) for initializing the variable @var{cum} for the state at the beginning of the argument list. The diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index a928c25b386..fd0817becbd 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,43 @@ +2008-06-02 Janus Weil <janus@gcc.gnu.org> + + PR fortran/36361 + * symbol.c (gfc_add_allocatable,gfc_add_dimension, + gfc_add_explicit_interface): Added checks. + * decl.c (attr_decl1): Added missing "var_locus". + * parse.c (parse_interface): Checking for errors. + +2008-06-02 Daniel Kraft <d@domob.eu> + + * gfortran.h: New statement-type ST_FINAL for FINAL declarations. + (struct gfc_symbol): New member f2k_derived. + (struct gfc_namespace): New member finalizers, for use in the above + mentioned f2k_derived namespace. + (struct gfc_finalizer): New type defined for finalizers linked list. + * match.h (gfc_match_final_decl): New function header. + * decl.c (gfc_match_derived_decl): Create f2k_derived namespace on + constructed symbol node. + (gfc_match_final_decl): New function to match a FINAL declaration line. + * parse.c (decode_statement): match-call for keyword FINAL. + (parse_derived): Parse CONTAINS section and accept FINAL statements. + * resolve.c (gfc_resolve_finalizers): New function to resolve (that is + in this case, check) a list of finalizer procedures. + (resolve_fl_derived): Call gfc_resolve_finalizers here. + * symbol.c (gfc_get_namespace): Initialize new finalizers to NULL. + (gfc_free_namespace): Free finalizers list. + (gfc_new_symbol): Initialize new f2k_derived to NULL. + (gfc_free_symbol): Free f2k_derived namespace. + (gfc_free_finalizer): New function to free a single gfc_finalizer node. + (gfc_free_finalizer_list): New function to free a linked list of + gfc_finalizer nodes. + +2008-06-02 Daniel Franke <franke.daniel@gmail.com> + + PR fortran/36375 + PR fortran/36377 + * cpp.c (gfc_cpp_init): Do not initialize builtins if + processing already preprocessed input. + (gfc_cpp_preprocess): Finalize output with newline. + 2008-05-31 Jerry DeLisle <jvdelisle@gcc.gnu.org> * intrinsic.texi: Revert wrong commit. diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c index 865e2efc79d..170f6cdcd63 100644 --- a/gcc/fortran/cpp.c +++ b/gcc/fortran/cpp.c @@ -524,6 +524,9 @@ gfc_cpp_init (void) { int i; + if (gfc_option.flag_preprocessed) + return; + cpp_change_file (cpp_in, LC_RENAME, _("<built-in>")); if (!gfc_cpp_option.no_predefined) cpp_define_builtins (cpp_in); @@ -574,6 +577,8 @@ gfc_cpp_preprocess (const char *source_file) cpp_forall_identifiers (cpp_in, dump_macro, NULL); } + putc ('\n', print.outf); + if (!gfc_cpp_preprocess_only () || (gfc_cpp_preprocess_only () && gfc_cpp_option.output_filename)) fclose (print.outf); diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 79044eb1846..ea87c211d49 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -5216,7 +5216,7 @@ attr_decl1 (void) /* Update symbol table. DIMENSION attribute is set in gfc_set_array_spec(). */ if (current_attr.dimension == 0 - && gfc_copy_attr (&sym->attr, ¤t_attr, NULL) == FAILURE) + && gfc_copy_attr (&sym->attr, ¤t_attr, &var_locus) == FAILURE) { m = MATCH_ERROR; goto cleanup; @@ -6270,6 +6270,10 @@ gfc_match_derived_decl (void) if (attr.is_bind_c != 0) sym->attr.is_bind_c = attr.is_bind_c; + /* Construct the f2k_derived namespace if it is not yet there. */ + if (!sym->f2k_derived) + sym->f2k_derived = gfc_get_namespace (NULL, 0); + gfc_new_block = sym; return MATCH_YES; @@ -6480,3 +6484,105 @@ cleanup: } +/* Match a FINAL declaration inside a derived type. */ + +match +gfc_match_final_decl (void) +{ + char name[GFC_MAX_SYMBOL_LEN + 1]; + gfc_symbol* sym; + match m; + gfc_namespace* module_ns; + bool first, last; + + if (gfc_state_stack->state != COMP_DERIVED) + { + gfc_error ("FINAL declaration at %C must be inside a derived type " + "definition!"); + return MATCH_ERROR; + } + + gcc_assert (gfc_current_block ()); + + if (!gfc_state_stack->previous + || gfc_state_stack->previous->state != COMP_MODULE) + { + gfc_error ("Derived type declaration with FINAL at %C must be in the" + " specification part of a MODULE"); + return MATCH_ERROR; + } + + module_ns = gfc_current_ns; + gcc_assert (module_ns); + gcc_assert (module_ns->proc_name->attr.flavor == FL_MODULE); + + /* Match optional ::, don't care about MATCH_YES or MATCH_NO. */ + if (gfc_match (" ::") == MATCH_ERROR) + return MATCH_ERROR; + + /* Match the sequence of procedure names. */ + first = true; + last = false; + do + { + gfc_finalizer* f; + + if (first && gfc_match_eos () == MATCH_YES) + { + gfc_error ("Empty FINAL at %C"); + return MATCH_ERROR; + } + + m = gfc_match_name (name); + if (m == MATCH_NO) + { + gfc_error ("Expected module procedure name at %C"); + return MATCH_ERROR; + } + else if (m != MATCH_YES) + return MATCH_ERROR; + + if (gfc_match_eos () == MATCH_YES) + last = true; + if (!last && gfc_match_char (',') != MATCH_YES) + { + gfc_error ("Expected ',' at %C"); + return MATCH_ERROR; + } + + if (gfc_get_symbol (name, module_ns, &sym)) + { + gfc_error ("Unknown procedure name \"%s\" at %C", name); + return MATCH_ERROR; + } + + /* Mark the symbol as module procedure. */ + if (sym->attr.proc != PROC_MODULE + && gfc_add_procedure (&sym->attr, PROC_MODULE, + sym->name, NULL) == FAILURE) + return MATCH_ERROR; + + /* Check if we already have this symbol in the list, this is an error. */ + for (f = gfc_current_block ()->f2k_derived->finalizers; f; f = f->next) + if (f->procedure == sym) + { + gfc_error ("'%s' at %C is already defined as FINAL procedure!", + name); + return MATCH_ERROR; + } + + /* Add this symbol to the list of finalizers. */ + gcc_assert (gfc_current_block ()->f2k_derived); + ++sym->refs; + f = gfc_getmem (sizeof (gfc_finalizer)); + f->procedure = sym; + f->where = gfc_current_locus; + f->next = gfc_current_block ()->f2k_derived->finalizers; + gfc_current_block ()->f2k_derived->finalizers = f; + + first = false; + } + while (!last); + + return MATCH_YES; +} diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index e3a9446333e..d4f9771e610 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -210,7 +210,7 @@ typedef enum ST_CALL, ST_CASE, ST_CLOSE, ST_COMMON, ST_CONTINUE, ST_CONTAINS, ST_CYCLE, ST_DATA, ST_DATA_DECL, ST_DEALLOCATE, ST_DO, ST_ELSE, ST_ELSEIF, ST_ELSEWHERE, ST_END_BLOCK_DATA, ST_ENDDO, ST_IMPLIED_ENDDO, - ST_END_FILE, ST_FLUSH, ST_END_FORALL, ST_END_FUNCTION, ST_ENDIF, + ST_END_FILE, ST_FINAL, ST_FLUSH, ST_END_FORALL, ST_END_FUNCTION, ST_ENDIF, ST_END_INTERFACE, ST_END_MODULE, ST_END_PROGRAM, ST_END_SELECT, ST_END_SUBROUTINE, ST_END_WHERE, ST_END_TYPE, ST_ENTRY, ST_EQUIVALENCE, ST_EXIT, ST_FORALL, ST_FORALL_BLOCK, ST_FORMAT, ST_FUNCTION, ST_GOTO, @@ -1014,6 +1014,10 @@ typedef struct gfc_symbol gfc_formal_arglist *formal; struct gfc_namespace *formal_ns; + /* The namespace containing type-associated procedure symbols. */ + /* TODO: Make this union with formal? */ + struct gfc_namespace *f2k_derived; + struct gfc_expr *value; /* Parameter/Initializer value */ gfc_array_spec *as; struct gfc_symbol *result; /* function result symbol */ @@ -1151,6 +1155,8 @@ typedef struct gfc_namespace gfc_symtree *uop_root; /* Tree containing all the common blocks. */ gfc_symtree *common_root; + /* Linked list of finalizer procedures. */ + struct gfc_finalizer *finalizers; /* If set_flag[letter] is set, an implicit type has been set for letter. */ int set_flag[GFC_LETTERS]; @@ -1942,6 +1948,17 @@ typedef struct iterator_stack iterator_stack; extern iterator_stack *iter_stack; + +/* Node in the linked list used for storing finalizer procedures. */ + +typedef struct gfc_finalizer +{ + struct gfc_finalizer* next; + gfc_symbol* procedure; + locus where; /* Where the FINAL declaration occured. */ +} +gfc_finalizer; + /************************ Function prototypes *************************/ /* decl.c */ @@ -2210,6 +2227,8 @@ gfc_gsymbol *gfc_find_gsymbol (gfc_gsymbol *, const char *); void copy_formal_args (gfc_symbol *dest, gfc_symbol *src); +void gfc_free_finalizer (gfc_finalizer *el); /* Needed in resolve.c, too */ + /* intrinsic.c */ extern int gfc_init_expr; diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h index d46e1630136..3f8d31074e8 100644 --- a/gcc/fortran/match.h +++ b/gcc/fortran/match.h @@ -140,6 +140,7 @@ match gfc_match_function_decl (void); match gfc_match_entry (void); match gfc_match_subroutine (void); match gfc_match_derived_decl (void); +match gfc_match_final_decl (void); match gfc_match_implicit_none (void); match gfc_match_implicit (void); diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index b7e63919e8e..33f13c92200 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -366,6 +366,7 @@ decode_statement (void) break; case 'f': + match ("final", gfc_match_final_decl, ST_FINAL); match ("flush", gfc_match_flush, ST_FLUSH); match ("format", gfc_match_format, ST_FORMAT); break; @@ -1682,6 +1683,7 @@ static void parse_derived (void) { int compiling_type, seen_private, seen_sequence, seen_component, error_flag; + int seen_contains, seen_contains_comp; gfc_statement st; gfc_state_data s; gfc_symbol *derived_sym = NULL; @@ -1697,6 +1699,8 @@ parse_derived (void) seen_private = 0; seen_sequence = 0; seen_component = 0; + seen_contains = 0; + seen_contains_comp = 0; compiling_type = 1; @@ -1710,23 +1714,57 @@ parse_derived (void) case ST_DATA_DECL: case ST_PROCEDURE: + if (seen_contains) + { + gfc_error ("Components in TYPE at %C must precede CONTAINS"); + error_flag = 1; + } + accept_statement (st); seen_component = 1; break; + case ST_FINAL: + if (!seen_contains) + { + gfc_error ("FINAL declaration at %C must be inside CONTAINS"); + error_flag = 1; + } + + if (gfc_notify_std (GFC_STD_F2003, + "Fortran 2003: FINAL procedure declaration" + " at %C") == FAILURE) + error_flag = 1; + + accept_statement (ST_FINAL); + seen_contains_comp = 1; + break; + case ST_END_TYPE: compiling_type = 0; if (!seen_component && (gfc_notify_std (GFC_STD_F2003, "Fortran 2003: Derived type " - "definition at %C without components") + "definition at %C without components") == FAILURE)) error_flag = 1; + if (seen_contains && !seen_contains_comp + && (gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Derived type " + "definition at %C with empty CONTAINS " + "section") == FAILURE)) + error_flag = 1; + accept_statement (ST_END_TYPE); break; case ST_PRIVATE: + if (seen_contains) + { + gfc_error ("PRIVATE statement at %C must precede CONTAINS"); + error_flag = 1; + } + if (gfc_find_state (COMP_MODULE) == FAILURE) { gfc_error ("PRIVATE statement in TYPE at %C must be inside " @@ -1755,6 +1793,12 @@ parse_derived (void) break; case ST_SEQUENCE: + if (seen_contains) + { + gfc_error ("SEQUENCE statement at %C must precede CONTAINS"); + error_flag = 1; + } + if (seen_component) { gfc_error ("SEQUENCE statement at %C must precede " @@ -1778,6 +1822,22 @@ parse_derived (void) gfc_current_block ()->name, NULL); break; + case ST_CONTAINS: + if (gfc_notify_std (GFC_STD_F2003, + "Fortran 2003: CONTAINS block in derived type" + " definition at %C") == FAILURE) + error_flag = 1; + + if (seen_contains) + { + gfc_error ("Already inside a CONTAINS block at %C"); + error_flag = 1; + } + + seen_contains = 1; + accept_statement (ST_CONTAINS); + break; + default: unexpected_statement (st); break; @@ -1914,23 +1974,18 @@ loop: unexpected_eof (); case ST_SUBROUTINE: - new_state = COMP_SUBROUTINE; - gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY, - gfc_new_block->formal, NULL); - if (current_interface.type != INTERFACE_ABSTRACT && - !gfc_new_block->attr.dummy && - gfc_add_external (&gfc_new_block->attr, &gfc_current_locus) == FAILURE) + case ST_FUNCTION: + if (st == ST_SUBROUTINE) + new_state = COMP_SUBROUTINE; + else if (st == ST_FUNCTION) + new_state = COMP_FUNCTION; + if (gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY, + gfc_new_block->formal, NULL) == FAILURE) { reject_statement (); gfc_free_namespace (gfc_current_ns); goto loop; } - break; - - case ST_FUNCTION: - new_state = COMP_FUNCTION; - gfc_add_explicit_interface (gfc_new_block, IFSRC_IFBODY, - gfc_new_block->formal, NULL); if (current_interface.type != INTERFACE_ABSTRACT && !gfc_new_block->attr.dummy && gfc_add_external (&gfc_new_block->attr, &gfc_current_locus) == FAILURE) diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 8044990b7dd..c9809351c94 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -7439,6 +7439,146 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag) } +/* Resolve a list of finalizer procedures. That is, after they have hopefully + been defined and we now know their defined arguments, check that they fulfill + the requirements of the standard for procedures used as finalizers. */ + +static try +gfc_resolve_finalizers (gfc_symbol* derived) +{ + gfc_finalizer* list; + gfc_finalizer** prev_link; /* For removing wrong entries from the list. */ + try result = SUCCESS; + bool seen_scalar = false; + + if (!derived->f2k_derived || !derived->f2k_derived->finalizers) + return SUCCESS; + + /* Walk over the list of finalizer-procedures, check them, and if any one + does not fit in with the standard's definition, print an error and remove + it from the list. */ + prev_link = &derived->f2k_derived->finalizers; + for (list = derived->f2k_derived->finalizers; list; list = *prev_link) + { + gfc_symbol* arg; + gfc_finalizer* i; + int my_rank; + + /* Check this exists and is a SUBROUTINE. */ + if (!list->procedure->attr.subroutine) + { + gfc_error ("FINAL procedure '%s' at %L is not a SUBROUTINE", + list->procedure->name, &list->where); + goto error; + } + + /* We should have exactly one argument. */ + if (!list->procedure->formal || list->procedure->formal->next) + { + gfc_error ("FINAL procedure at %L must have exactly one argument", + &list->where); + goto error; + } + arg = list->procedure->formal->sym; + + /* This argument must be of our type. */ + if (arg->ts.type != BT_DERIVED || arg->ts.derived != derived) + { + gfc_error ("Argument of FINAL procedure at %L must be of type '%s'", + &arg->declared_at, derived->name); + goto error; + } + + /* It must neither be a pointer nor allocatable nor optional. */ + if (arg->attr.pointer) + { + gfc_error ("Argument of FINAL procedure at %L must not be a POINTER", + &arg->declared_at); + goto error; + } + if (arg->attr.allocatable) + { + gfc_error ("Argument of FINAL procedure at %L must not be" + " ALLOCATABLE", &arg->declared_at); + goto error; + } + if (arg->attr.optional) + { + gfc_error ("Argument of FINAL procedure at %L must not be OPTIONAL", + &arg->declared_at); + goto error; + } + + /* It must not be INTENT(OUT). */ + if (arg->attr.intent == INTENT_OUT) + { + gfc_error ("Argument of FINAL procedure at %L must not be" + " INTENT(OUT)", &arg->declared_at); + goto error; + } + + /* Warn if the procedure is non-scalar and not assumed shape. */ + if (gfc_option.warn_surprising && arg->as && arg->as->rank > 0 + && arg->as->type != AS_ASSUMED_SHAPE) + gfc_warning ("Non-scalar FINAL procedure at %L should have assumed" + " shape argument", &arg->declared_at); + + /* Check that it does not match in kind and rank with a FINAL procedure + defined earlier. To really loop over the *earlier* declarations, + we need to walk the tail of the list as new ones were pushed at the + front. */ + /* TODO: Handle kind parameters once they are implemented. */ + my_rank = (arg->as ? arg->as->rank : 0); + for (i = list->next; i; i = i->next) + { + /* Argument list might be empty; that is an error signalled earlier, + but we nevertheless continued resolving. */ + if (i->procedure->formal) + { + gfc_symbol* i_arg = i->procedure->formal->sym; + const int i_rank = (i_arg->as ? i_arg->as->rank : 0); + if (i_rank == my_rank) + { + gfc_error ("FINAL procedure '%s' declared at %L has the same" + " rank (%d) as '%s'", + list->procedure->name, &list->where, my_rank, + i->procedure->name); + goto error; + } + } + } + + /* Is this the/a scalar finalizer procedure? */ + if (!arg->as || arg->as->rank == 0) + seen_scalar = true; + + prev_link = &list->next; + continue; + + /* Remove wrong nodes immediatelly from the list so we don't risk any + troubles in the future when they might fail later expectations. */ +error: + result = FAILURE; + i = list; + *prev_link = list->next; + gfc_free_finalizer (i); + } + + /* Warn if we haven't seen a scalar finalizer procedure (but we know there + were nodes in the list, must have been for arrays. It is surely a good + idea to have a scalar version there if there's something to finalize. */ + if (gfc_option.warn_surprising && result == SUCCESS && !seen_scalar) + gfc_warning ("Only array FINAL procedures declared for derived type '%s'" + " defined at %L, suggest also scalar one", + derived->name, &derived->declared_at); + + /* TODO: Remove this error when finalization is finished. */ + gfc_error ("Finalization at %L is not yet implemented", &derived->declared_at); + + return result; +} + + /* Resolve the components of a derived type. */ static try @@ -7517,6 +7657,10 @@ resolve_fl_derived (gfc_symbol *sym) } } + /* Resolve the finalizer procedures. */ + if (gfc_resolve_finalizers (sym) == FAILURE) + return FAILURE; + /* Add derived type to the derived type list. */ for (dt_list = gfc_derived_types; dt_list; dt_list = dt_list->next) if (sym == dt_list->derived) diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index e98a19c57fa..e4e43244d59 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -814,6 +814,14 @@ gfc_add_allocatable (symbol_attribute *attr, locus *where) return FAILURE; } + if (attr->flavor == FL_PROCEDURE && attr->if_source == IFSRC_IFBODY + && gfc_find_state (COMP_INTERFACE) == FAILURE) + { + gfc_error ("ALLOCATABLE specified outside of INTERFACE body at %L", + where); + return FAILURE; + } + attr->allocatable = 1; return check_conflict (attr, NULL, where); } @@ -832,6 +840,14 @@ gfc_add_dimension (symbol_attribute *attr, const char *name, locus *where) return FAILURE; } + if (attr->flavor == FL_PROCEDURE && attr->if_source == IFSRC_IFBODY + && gfc_find_state (COMP_INTERFACE) == FAILURE) + { + gfc_error ("DIMENSION specified for '%s' outside its INTERFACE body " + "at %L", name, where); + return FAILURE; + } + attr->dimension = 1; return check_conflict (attr, name, where); } @@ -1453,6 +1469,13 @@ gfc_add_explicit_interface (gfc_symbol *sym, ifsrc source, return FAILURE; } + if (source == IFSRC_IFBODY && (sym->attr.dimension || sym->attr.allocatable)) + { + gfc_error ("'%s' at %L has attributes specified outside its INTERFACE " + "body", sym->name, where); + return FAILURE; + } + sym->formal = formal; sym->attr.if_source = source; @@ -2096,6 +2119,7 @@ gfc_get_namespace (gfc_namespace *parent, int parent_types) ns = gfc_getmem (sizeof (gfc_namespace)); ns->sym_root = NULL; ns->uop_root = NULL; + ns->finalizers = NULL; ns->default_access = ACCESS_UNKNOWN; ns->parent = parent; @@ -2284,6 +2308,8 @@ gfc_free_symbol (gfc_symbol *sym) gfc_free_formal_arglist (sym->formal); + gfc_free_namespace (sym->f2k_derived); + gfc_free (sym); } @@ -2316,6 +2342,7 @@ gfc_new_symbol (const char *name, gfc_namespace *ns) /* Clear the ptrs we may need. */ p->common_block = NULL; + p->f2k_derived = NULL; return p; } @@ -2884,6 +2911,33 @@ gfc_free_equiv_lists (gfc_equiv_list *l) } +/* Free a finalizer procedure list. */ + +void +gfc_free_finalizer (gfc_finalizer* el) +{ + if (el) + { + --el->procedure->refs; + if (!el->procedure->refs) + gfc_free_symbol (el->procedure); + + gfc_free (el); + } +} + +static void +gfc_free_finalizer_list (gfc_finalizer* list) +{ + while (list) + { + gfc_finalizer* current = list; + list = list->next; + gfc_free_finalizer (current); + } +} + + /* Free a namespace structure and everything below it. Interface lists associated with intrinsic operators are not freed. These are taken care of when a specific name is freed. */ @@ -2908,6 +2962,7 @@ gfc_free_namespace (gfc_namespace *ns) free_sym_tree (ns->sym_root); free_uop_tree (ns->uop_root); free_common_tree (ns->common_root); + gfc_free_finalizer_list (ns->finalizers); for (cl = ns->cl_list; cl; cl = cl2) { diff --git a/gcc/function.c b/gcc/function.c index bb4a2e6ab68..30dd9f302a0 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -3852,6 +3852,10 @@ allocate_struct_function (tree fndecl, bool abstract_p) if (init_machine_status) cfun->machine = (*init_machine_status) (); +#ifdef OVERRIDE_ABI_FORMAT + OVERRIDE_ABI_FORMAT (fndecl); +#endif + if (fndecl != NULL_TREE) { DECL_STRUCT_FUNCTION (fndecl) = cfun; diff --git a/gcc/predict.c b/gcc/predict.c index 41743331b9e..42852dcfcac 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -107,6 +107,22 @@ static const struct predictor_info predictor_info[]= { }; #undef DEF_PREDICTOR +/* Return TRUE if frequency FREQ is considered to be hot. */ +static bool +maybe_hot_frequency_p (int freq) +{ + if (!profile_info || !flag_branch_probabilities) + { + if (cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED) + return false; + if (cfun->function_frequency == FUNCTION_FREQUENCY_HOT) + return true; + } + if (freq < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)) + return false; + return true; +} + /* Return true in case BB can be CPU intensive and should be optimized for maximal performance. */ @@ -117,16 +133,20 @@ maybe_hot_bb_p (const_basic_block bb) && (bb->count < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION))) return false; - if (!profile_info || !flag_branch_probabilities) - { - if (cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED) - return false; - if (cfun->function_frequency == FUNCTION_FREQUENCY_HOT) - return true; - } - if (bb->frequency < BB_FREQ_MAX / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)) + return maybe_hot_frequency_p (bb->frequency); +} + +/* Return true in case BB can be CPU intensive and should be optimized + for maximal performance. */ + +bool +maybe_hot_edge_p (edge e) +{ + if (profile_info && flag_branch_probabilities + && (e->count + < profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION))) return false; - return true; + return maybe_hot_frequency_p (EDGE_FREQUENCY (e)); } /* Return true in case BB is cold and should be optimized for size. */ diff --git a/gcc/target-def.h b/gcc/target-def.h index 19e882f3787..69b6169bf47 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -545,9 +545,7 @@ #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false #define TARGET_STRUCT_VALUE_RTX hook_rtx_tree_int_null -#ifndef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY default_return_in_memory -#endif #define TARGET_RETURN_IN_MSB hook_bool_const_tree_false #define TARGET_EXPAND_BUILTIN_SAVEREGS default_expand_builtin_saveregs diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4cf3f8e1468..1f319a0e120 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,55 @@ +2008-06-02 Andy Hutchinson <hutchinsonandy@aim.com> + + * gcc.target/avr/avr.exp: Add avr testsuite. + * gcc.target/avr/trivial.c: Add simple test. + * gcc.target/avr/torture/avr-torture.exp: Add avr-torture testsuite. + * gcc.target/avr/torture/trivial.c: Add simple test. + +2008-06-02 Andy Hutchinson <hutchinsonandy@aim.com> + + * gcc.dg/pr19340.c: Disable for AVR as it has no scheduling. + * gcc.dg/section1.c: XFAIL AVR as bss section is used differently. + +2008-06-02 Andy Hutchinson <hutchinsonandy@aim.com> + + * gcc.dg/pr18241-1.c: Use long on small int target. + * gcc.dg/pr32912-2.c: Ditto. + * gcc.dg/pr35065.c: Ditto. + * gcc.dg/pr36300-1.c: Ditto. + * gcc.dg/pr36300-2.c: Ditto. + * gcc.dg/pr27639.c: Reduce array size for small int target. + * gcc.dg/pr28755.c: Skip test if pointers are smaller than 32 bits. + * gcc.dg/pr36194.c: Reduce constant on small int target. + * gcc.dg/torture/builtin-frexp-1.c: Ditto. + +2008-06-02 Andy Hutchinson <hutchinsonandy@aim.com> + + * gcc.dg/torture/pr34330.c: Skip test for targets without pthread. + * gcc.dg/torture/pr36244.c: Ditto. + * gcc.dg/tree-ssa/pr36181.c: Ditto. + +2008-06-02 Janus Weil <janus@gcc.gnu.org> + + PR fortran/36361 + * gfortran.dg/interface_24.f90: New. + +2008-06-02 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/36404 + * g++.dg/template/crash79.C: New. + * g++.dg/other/pr28114.C: Adjust. + +2008-06-02 Daniel Kraft <d@domob.eu> + + * finalize_1.f08: New test. + * finalize_2.f03: New test. + * finalize_3.f03: New test. + * finalize_4.f03: New test. + * finalize_5.f03: New test. + * finalize_6.f90: New test. + * finalize_7.f03: New test. + * finalize_8.f03: New test. + 2008-06-01 Richard Sandiford <rdsandiford@googlemail.com> * gcc.c-torture/execute/ieee/ieee.exp: Load c-torture.exp. diff --git a/gcc/testsuite/g++.dg/other/pr28114.C b/gcc/testsuite/g++.dg/other/pr28114.C index 05aeebb8055..e16f6b589e5 100644 --- a/gcc/testsuite/g++.dg/other/pr28114.C +++ b/gcc/testsuite/g++.dg/other/pr28114.C @@ -5,5 +5,5 @@ template<int> void foo(struct {}*); // { dg-error "" } void bar() { - foo<0>(0); // { dg-error "" } + foo<0>(0); } diff --git a/gcc/testsuite/g++.dg/template/crash79.C b/gcc/testsuite/g++.dg/template/crash79.C new file mode 100644 index 00000000000..be71848fe83 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/crash79.C @@ -0,0 +1,9 @@ +// PR c++/36404 + +struct A +{ + A(int); + template<int> enum { e }; // { dg-error "template" } +}; + +A a(A::e); // { dg-error "not a member" } diff --git a/gcc/testsuite/gcc.dg/pr18241-1.c b/gcc/testsuite/gcc.dg/pr18241-1.c index d6bdbccf8de..a37e77dac64 100644 --- a/gcc/testsuite/gcc.dg/pr18241-1.c +++ b/gcc/testsuite/gcc.dg/pr18241-1.c @@ -27,7 +27,11 @@ static inline void tag_clear(struct radix_tree_node *node, int tag, int offset) { int nr; volatile unsigned long *addr; +#if(__SIZEOF_INT__ >= 4) int mask; +#else + long mask; +#endif nr = offset; addr = &node->tags[tag][0]; diff --git a/gcc/testsuite/gcc.dg/pr19340.c b/gcc/testsuite/gcc.dg/pr19340.c index a5ff410ff48..844d80677d0 100644 --- a/gcc/testsuite/gcc.dg/pr19340.c +++ b/gcc/testsuite/gcc.dg/pr19340.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O1 -fschedule-insns2 -fsched2-use-traces" } */ -/* { dg-skip-if "No scheduling" { mmix-*-* cris-*-* crisv32-*-* fido-*-* m68k-*-* m32c-*-* } { "*" } { "" } } */ +/* { dg-skip-if "No scheduling" { mmix-*-* cris-*-* crisv32-*-* fido-*-* m68k-*-* m32c-*-* avr-*-* } { "*" } { "" } } */ extern double f (double x); diff --git a/gcc/testsuite/gcc.dg/pr27639.c b/gcc/testsuite/gcc.dg/pr27639.c index 28e4223d81d..cb7b1429d4d 100644 --- a/gcc/testsuite/gcc.dg/pr27639.c +++ b/gcc/testsuite/gcc.dg/pr27639.c @@ -1,8 +1,10 @@ /* { dg-do compile } */ /* { dg-options "-O2 -std=c99" } */ - +#if(__SIZEOF_INT__ >= 4) char heap[50000]; - +#else +char heap[32000]; +#endif int main () { diff --git a/gcc/testsuite/gcc.dg/pr28755.c b/gcc/testsuite/gcc.dg/pr28755.c index 9a01f88d0d9..9cd1330d1dd 100644 --- a/gcc/testsuite/gcc.dg/pr28755.c +++ b/gcc/testsuite/gcc.dg/pr28755.c @@ -1,5 +1,6 @@ /* PR middle-end/28755 */ /* { dg-do compile } */ +/* { dg-require-effective-target ptr32plus } */ /* { dg-options "-Os" } */ /* { dg-final { scan-assembler-times "2112543726\|7deadbee" 2 } } */ diff --git a/gcc/testsuite/gcc.dg/pr32912-2.c b/gcc/testsuite/gcc.dg/pr32912-2.c index 6f028744c60..f3c754cc346 100644 --- a/gcc/testsuite/gcc.dg/pr32912-2.c +++ b/gcc/testsuite/gcc.dg/pr32912-2.c @@ -3,8 +3,11 @@ extern void abort (void); +#if(__SIZEOF_INT__ >= 4) typedef int __m128i __attribute__ ((__vector_size__ (16))); - +#else +typedef long __m128i __attribute__ ((__vector_size__ (16))); +#endif __m128i foo (void) { @@ -22,7 +25,11 @@ bar (void) int main (void) { +#if(__SIZEOF_INT__ >= 4) union { __m128i v; int i[sizeof (__m128i) / sizeof (int)]; } u, v; +#else + union { __m128i v; long i[sizeof (__m128i) / sizeof (long)]; } u, v; +#endif int i; u.v = foo (); diff --git a/gcc/testsuite/gcc.dg/pr35065.c b/gcc/testsuite/gcc.dg/pr35065.c index 3ed46642ffc..e5984ab0f82 100644 --- a/gcc/testsuite/gcc.dg/pr35065.c +++ b/gcc/testsuite/gcc.dg/pr35065.c @@ -5,7 +5,11 @@ typedef int vlc_bool_t; typedef __SIZE_TYPE__ size_t; typedef struct vlc_object_t vlc_object_t; typedef long long int64_t; +#if(__SIZEOF_INT__ >= 4) typedef unsigned int uint32_t; +#else +typedef unsigned long uint32_t; +#endif typedef unsigned char uint8_t; typedef int64_t mtime_t; typedef uint32_t vlc_fourcc_t; diff --git a/gcc/testsuite/gcc.dg/pr36194.c b/gcc/testsuite/gcc.dg/pr36194.c index 3d2195b03d4..070a944e97f 100644 --- a/gcc/testsuite/gcc.dg/pr36194.c +++ b/gcc/testsuite/gcc.dg/pr36194.c @@ -6,7 +6,11 @@ void abort (void); __attribute__ ((noinline)) void f (int i) { +#if(__SIZEOF_INT__ >= 4) if (i != 0x87654321) +#else + if (i != 0x4321) +#endif abort (); asm (""); } diff --git a/gcc/testsuite/gcc.dg/pr36300-1.c b/gcc/testsuite/gcc.dg/pr36300-1.c index 466522f8b79..e737ab7ff0c 100644 --- a/gcc/testsuite/gcc.dg/pr36300-1.c +++ b/gcc/testsuite/gcc.dg/pr36300-1.c @@ -7,10 +7,13 @@ extern void abort (void); int main(void) { - int U1; long long Y, Y2; +#if(__SIZEOF_INT__ >= 4) + int U1; +#else + long U1; +#endif int t; - U1 = -2147483647-1; Y = ((long long)(VALUE * VALUE) * 3); diff --git a/gcc/testsuite/gcc.dg/pr36300-2.c b/gcc/testsuite/gcc.dg/pr36300-2.c index 7e7cfa2b7eb..9543332683e 100644 --- a/gcc/testsuite/gcc.dg/pr36300-2.c +++ b/gcc/testsuite/gcc.dg/pr36300-2.c @@ -7,8 +7,12 @@ extern void abort (void); int main(void) { - int U1; long long Y, Y2; +#if(__SIZEOF_INT__ >= 4) + int U1; +#else + long U1; +#endif unsigned int t; U1 = -2147483647-1; diff --git a/gcc/testsuite/gcc.dg/section1.c b/gcc/testsuite/gcc.dg/section1.c index e907f193b0f..39ca969a572 100644 --- a/gcc/testsuite/gcc.dg/section1.c +++ b/gcc/testsuite/gcc.dg/section1.c @@ -1,5 +1,5 @@ /* PR optimization/6871 */ /* Constant variables belong in .rodata, not .bss. */ -/* { dg-final { scan-assembler-not "\.bss" } } */ +/* { dg-final { scan-assembler-not "\.bss" { xfail avr-*-*} } } */ const int i = 0; diff --git a/gcc/testsuite/gcc.dg/torture/builtin-frexp-1.c b/gcc/testsuite/gcc.dg/torture/builtin-frexp-1.c index cb97e8e4e16..2225f825b82 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-frexp-1.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-frexp-1.c @@ -34,17 +34,17 @@ extern void link_error(int); /* Test that frexp(ARG,&i) == RES && i == EXP. Check the sign in case we get -0.0. */ #define TESTIT_FREXP(ARG,RES,EXP) do { \ - int i = 123456; \ + int i = 12345; \ if (__builtin_frexpf(ARG##f,&i) != RES##f \ || CKEXP(i,EXP) \ || CKSGN_F(__builtin_frexpf(ARG##f,&i),RES##f)) \ link_error(__LINE__); \ - i = 123456; \ + i = 12345; \ if (__builtin_frexp(ARG,&i) != RES \ || CKEXP(i,EXP) \ || CKSGN(__builtin_frexp(ARG,&i),RES)) \ link_error(__LINE__); \ - i = 123456; \ + i = 12345; \ if (__builtin_frexpl(ARG##l,&i) != RES##l \ || CKEXP(i,EXP) \ || CKSGN_L(__builtin_frexpl(ARG##l,&i),RES##l)) \ diff --git a/gcc/testsuite/gcc.dg/torture/pr34330.c b/gcc/testsuite/gcc.dg/torture/pr34330.c index 85cfe37e8ad..0ed2f9fb395 100644 --- a/gcc/testsuite/gcc.dg/torture/pr34330.c +++ b/gcc/testsuite/gcc.dg/torture/pr34330.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-require-effective-target pthread } */ /* { dg-options "-ftree-parallelize-loops=4 -ftree-vectorize" } */ struct T diff --git a/gcc/testsuite/gcc.dg/torture/pr36244.c b/gcc/testsuite/gcc.dg/torture/pr36244.c index 9daa29e2f10..b1b14be1891 100644 --- a/gcc/testsuite/gcc.dg/torture/pr36244.c +++ b/gcc/testsuite/gcc.dg/torture/pr36244.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-require-effective-target pthread } */ /* { dg-options "-O3 -ftree-parallelize-loops=4" } */ struct p7prior_s { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr36181.c b/gcc/testsuite/gcc.dg/tree-ssa/pr36181.c index 6eda0a4270a..7294c07b14b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr36181.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr36181.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-require-effective-target pthread } */ /* { dg-options "-O3 -ftree-parallelize-loops=2" } */ int foo () diff --git a/gcc/testsuite/gcc.target/avr/avr.exp b/gcc/testsuite/gcc.target/avr/avr.exp new file mode 100644 index 00000000000..90aeed41e1f --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/avr.exp @@ -0,0 +1,41 @@ +# Copyright (C) 2008 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an AVR target.
+if ![istarget avr-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
+ "" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/avr/torture/avr-torture.exp b/gcc/testsuite/gcc.target/avr/torture/avr-torture.exp new file mode 100644 index 00000000000..355b3ad88bd --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/avr-torture.exp @@ -0,0 +1,61 @@ +# Copyright (C) 2008 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+#
+# This program 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/>.
+
+# GCC testsuite that uses the `gcc-dg.exp' driver, looping over
+# optimization options.
+
+# Exit immediately if this isn't a AVR target.
+if { ![istarget avr-*-*] } then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+ set AVR_TORTURE_OPTIONS [list \
+ { -O0 } \
+ { -O1 } \
+ { -O2 } \
+ { -O2 -mcall-prologues } \
+ { -Os -fomit-frame-pointer } \
+ { -Os -fomit-frame-pointer -finline-functions } \
+ { -O3 -g } \
+ { -Os -mcall-prologues} ]
+
+
+#Initialize use of torture lists.
+torture-init
+
+set-torture-options $AVR_TORTURE_OPTIONS
+
+
+# Main loop.
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] $DEFAULT_CFLAGS
+
+# Finalize use of torture lists.
+torture-finish
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/avr/torture/trivial.c b/gcc/testsuite/gcc.target/avr/torture/trivial.c new file mode 100644 index 00000000000..91163f9226e --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/trivial.c @@ -0,0 +1,14 @@ +/* { dg-do run } */
+#include <stdio.h>
+
+#define __ATTR_PROGMEM__ __attribute__((__progmem__))
+
+#define PROGMEM __ATTR_PROGMEM__
+char PROGMEM a1 = 0x12;
+int PROGMEM a2 = 0x2345;
+long PROGMEM a3 = 0x12345678;
+int main(void)
+{
+ printf("Hello World\n");
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/trivial.c b/gcc/testsuite/gcc.target/avr/trivial.c new file mode 100644 index 00000000000..91163f9226e --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/trivial.c @@ -0,0 +1,14 @@ +/* { dg-do run } */
+#include <stdio.h>
+
+#define __ATTR_PROGMEM__ __attribute__((__progmem__))
+
+#define PROGMEM __ATTR_PROGMEM__
+char PROGMEM a1 = 0x12;
+int PROGMEM a2 = 0x2345;
+long PROGMEM a3 = 0x12345678;
+int main(void)
+{
+ printf("Hello World\n");
+ return 0;
+}
diff --git a/gcc/testsuite/gfortran.dg/finalize_1.f08 b/gcc/testsuite/gfortran.dg/finalize_1.f08 new file mode 100644 index 00000000000..e1501ef66b8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/finalize_1.f08 @@ -0,0 +1,31 @@ +! { dg-do compile } + +! Parsing of finalizer procedure definitions. +! Check that CONTAINS is allowed in TYPE definition; but empty only for F2008 + +MODULE final_type + IMPLICIT NONE + + TYPE :: mytype + INTEGER, ALLOCATABLE :: fooarr(:) + REAL :: foobar + CONTAINS + END TYPE mytype + +CONTAINS + + SUBROUTINE bar + TYPE :: t + CONTAINS ! This is ok + END TYPE t + ! Nothing + END SUBROUTINE bar + +END MODULE final_type + +PROGRAM finalizer + IMPLICIT NONE + ! Do nothing here +END PROGRAM finalizer + +! { dg-final { cleanup-modules "final_type" } } diff --git a/gcc/testsuite/gfortran.dg/finalize_2.f03 b/gcc/testsuite/gfortran.dg/finalize_2.f03 new file mode 100644 index 00000000000..b91bedff81f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/finalize_2.f03 @@ -0,0 +1,23 @@ +! { dg-do compile } +! { dg-options "-std=f2003" } + +! Parsing of finalizer procedure definitions. +! Check empty CONTAINS errors out for F2003. + +MODULE final_type + IMPLICIT NONE + + TYPE :: mytype + INTEGER, ALLOCATABLE :: fooarr(:) + REAL :: foobar + CONTAINS + END TYPE mytype ! { dg-error "Fortran 2008" } + +END MODULE final_type + +PROGRAM finalizer + IMPLICIT NONE + ! Do nothing here +END PROGRAM finalizer + +! { dg-final { cleanup-modules "final_type" } } diff --git a/gcc/testsuite/gfortran.dg/finalize_3.f03 b/gcc/testsuite/gfortran.dg/finalize_3.f03 new file mode 100644 index 00000000000..edc493bfca5 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/finalize_3.f03 @@ -0,0 +1,25 @@ +! { dg-do compile } + +! Parsing of finalizer procedure definitions. +! Check that CONTAINS disallows further components and no double CONTAINS +! is allowed. + +MODULE final_type + IMPLICIT NONE + + TYPE :: mytype + INTEGER, ALLOCATABLE :: fooarr(:) + REAL :: foobar + CONTAINS + CONTAINS ! { dg-error "Already inside a CONTAINS block" } + INTEGER :: x ! { dg-error "must precede CONTAINS" } + END TYPE mytype + +END MODULE final_type + +PROGRAM finalizer + IMPLICIT NONE + ! Do nothing here +END PROGRAM finalizer + +! { dg-final { cleanup-modules "final_type" } } diff --git a/gcc/testsuite/gfortran.dg/finalize_4.f03 b/gcc/testsuite/gfortran.dg/finalize_4.f03 new file mode 100644 index 00000000000..6e99256c252 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/finalize_4.f03 @@ -0,0 +1,55 @@ +! { dg-do compile } + +! Parsing of finalizer procedure definitions. +! Check parsing of valid finalizer definitions. + +MODULE final_type + IMPLICIT NONE + + TYPE :: mytype + INTEGER, ALLOCATABLE :: fooarr(:) + REAL :: foobar + CONTAINS + FINAL :: finalize_single + FINAL finalize_vector, finalize_matrix + ! TODO: Test with different kind type parameters once they are implemented. + END TYPE mytype + +CONTAINS + + ELEMENTAL SUBROUTINE finalize_single (el) + IMPLICIT NONE + TYPE(mytype), INTENT(IN) :: el + ! Do nothing in this test + END SUBROUTINE finalize_single + + SUBROUTINE finalize_vector (el) + IMPLICIT NONE + TYPE(mytype), INTENT(INOUT) :: el(:) + ! Do nothing in this test + END SUBROUTINE finalize_vector + + SUBROUTINE finalize_matrix (el) + IMPLICIT NONE + TYPE(mytype) :: el(:, :) + ! Do nothing in this test + END SUBROUTINE finalize_matrix + +END MODULE final_type + +PROGRAM finalizer + USE final_type, ONLY: mytype + IMPLICIT NONE + + TYPE(mytype) :: el, vec(42) + TYPE(mytype), ALLOCATABLE :: mat(:, :) + + ALLOCATE(mat(2, 3)) + DEALLOCATE(mat) + +END PROGRAM finalizer + +! TODO: Remove this once finalization is implemented. +! { dg-excess-errors "not yet implemented" } + +! { dg-final { cleanup-modules "final_type" } } diff --git a/gcc/testsuite/gfortran.dg/finalize_5.f03 b/gcc/testsuite/gfortran.dg/finalize_5.f03 new file mode 100644 index 00000000000..9f5dc1784d0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/finalize_5.f03 @@ -0,0 +1,114 @@ +! { dg-do compile } + +! Parsing of finalizer procedure definitions. +! Check for appropriate errors on invalid final procedures. + +MODULE final_type + IMPLICIT NONE + + TYPE :: mytype + INTEGER, ALLOCATABLE :: fooarr(:) + REAL :: foobar + FINAL :: finalize_matrix ! { dg-error "must be inside CONTAINS" } + CONTAINS + FINAL :: ! { dg-error "Empty FINAL" } + FINAL ! { dg-error "Empty FINAL" } + FINAL :: + ! { dg-error "Expected module procedure name" } + FINAL :: iamnot ! { dg-error "is not a SUBROUTINE" } + FINAL :: finalize_single finalize_vector ! { dg-error "Expected ','" } + FINAL :: finalize_single, finalize_vector + FINAL :: finalize_single ! { dg-error "is already defined" } + FINAL :: finalize_vector_2 ! { dg-error "has the same rank" } + FINAL :: finalize_single_2 ! { dg-error "has the same rank" } + FINAL :: bad_function ! { dg-error "is not a SUBROUTINE" } + FINAL bad_num_args_1 ! { dg-error "must have exactly one argument" } + FINAL bad_num_args_2 ! { dg-error "must have exactly one argument" } + FINAL bad_arg_type + FINAL :: bad_pointer + FINAL :: bad_alloc + FINAL :: bad_optional + FINAL :: bad_intent_out + + ! TODO: Test for polymorphism, kind parameters once those are implemented. + END TYPE mytype + +CONTAINS + + SUBROUTINE finalize_single (el) + IMPLICIT NONE + TYPE(mytype) :: el + END SUBROUTINE finalize_single + + ELEMENTAL SUBROUTINE finalize_single_2 (el) + IMPLICIT NONE + TYPE(mytype), INTENT(IN) :: el + END SUBROUTINE finalize_single_2 + + SUBROUTINE finalize_vector (el) + IMPLICIT NONE + TYPE(mytype), INTENT(INOUT) :: el(:) + END SUBROUTINE finalize_vector + + SUBROUTINE finalize_vector_2 (el) + IMPLICIT NONE + TYPE(mytype), INTENT(IN) :: el(:) + END SUBROUTINE finalize_vector_2 + + SUBROUTINE finalize_matrix (el) + IMPLICIT NONE + TYPE(mytype) :: el(:, :) + END SUBROUTINE finalize_matrix + + INTEGER FUNCTION bad_function (el) + IMPLICIT NONE + TYPE(mytype) :: el + + bad_function = 42 + END FUNCTION bad_function + + SUBROUTINE bad_num_args_1 () + IMPLICIT NONE + END SUBROUTINE bad_num_args_1 + + SUBROUTINE bad_num_args_2 (el, x) + IMPLICIT NONE + TYPE(mytype) :: el + COMPLEX :: x + END SUBROUTINE bad_num_args_2 + + SUBROUTINE bad_arg_type (el) ! { dg-error "must be of type 'mytype'" } + IMPLICIT NONE + REAL :: el + END SUBROUTINE bad_arg_type + + SUBROUTINE bad_pointer (el) ! { dg-error "must not be a POINTER" } + IMPLICIT NONE + TYPE(mytype), POINTER :: el + END SUBROUTINE bad_pointer + + SUBROUTINE bad_alloc (el) ! { dg-error "must not be ALLOCATABLE" } + IMPLICIT NONE + TYPE(mytype), ALLOCATABLE :: el(:) + END SUBROUTINE bad_alloc + + SUBROUTINE bad_optional (el) ! { dg-error "must not be OPTIONAL" } + IMPLICIT NONE + TYPE(mytype), OPTIONAL :: el + END SUBROUTINE bad_optional + + SUBROUTINE bad_intent_out (el) ! { dg-error "must not be INTENT\\(OUT\\)" } + IMPLICIT NONE + TYPE(mytype), INTENT(OUT) :: el + END SUBROUTINE bad_intent_out + +END MODULE final_type + +PROGRAM finalizer + IMPLICIT NONE + ! Nothing here, errors above +END PROGRAM finalizer + +! TODO: Remove this once finalization is implemented. +! { dg-excess-errors "not yet implemented" } + +! { dg-final { cleanup-modules "final_type" } } diff --git a/gcc/testsuite/gfortran.dg/finalize_6.f90 b/gcc/testsuite/gfortran.dg/finalize_6.f90 new file mode 100644 index 00000000000..e790f4efb10 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/finalize_6.f90 @@ -0,0 +1,35 @@ +! { dg-do compile } +! { dg-options "-std=f95" } + +! Parsing of finalizer procedure definitions. +! Check that CONTAINS/FINAL in derived types is rejected for F95. + +MODULE final_type + IMPLICIT NONE + + TYPE :: mytype + INTEGER :: fooarr(42) + REAL :: foobar + CONTAINS ! { dg-error "Fortran 2003" } + FINAL :: finalize_single ! { dg-error "Fortran 2003" } + END TYPE mytype + +CONTAINS + + SUBROUTINE finalize_single (el) + IMPLICIT NONE + TYPE(mytype) :: el + ! Do nothing in this test + END SUBROUTINE finalize_single + +END MODULE final_type + +PROGRAM finalizer + IMPLICIT NONE + ! Do nothing +END PROGRAM finalizer + +! TODO: Remove this once finalization is implemented. +! { dg-excess-errors "not yet implemented" } + +! { dg-final { cleanup-modules "final_type" } } diff --git a/gcc/testsuite/gfortran.dg/finalize_7.f03 b/gcc/testsuite/gfortran.dg/finalize_7.f03 new file mode 100644 index 00000000000..db6b4bea948 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/finalize_7.f03 @@ -0,0 +1,59 @@ +! { dg-do compile } +! { dg-options "-Wsurprising" } + +! Implementation of finalizer procedures. +! Check for expected warnings on dubious FINAL constructs. + +MODULE final_type + IMPLICIT NONE + + TYPE :: type_1 + INTEGER, ALLOCATABLE :: fooarr(:) + REAL :: foobar + CONTAINS + ! Non-scalar procedures should be assumed shape + FINAL :: fin1_scalar + FINAL :: fin1_shape_1 + FINAL :: fin1_shape_2 + END TYPE type_1 + + TYPE :: type_2 ! { dg-warning "Only array FINAL procedures" } + REAL :: x + CONTAINS + ! No scalar finalizer, only array ones + FINAL :: fin2_vector + END TYPE type_2 + +CONTAINS + + SUBROUTINE fin1_scalar (el) + IMPLICIT NONE + TYPE(type_1) :: el + END SUBROUTINE fin1_scalar + + SUBROUTINE fin1_shape_1 (v) ! { dg-warning "assumed shape" } + IMPLICIT NONE + TYPE(type_1) :: v(*) + END SUBROUTINE fin1_shape_1 + + SUBROUTINE fin1_shape_2 (v) ! { dg-warning "assumed shape" } + IMPLICIT NONE + TYPE(type_1) :: v(42, 5) + END SUBROUTINE fin1_shape_2 + + SUBROUTINE fin2_vector (v) + IMPLICIT NONE + TYPE(type_2) :: v(:) + END SUBROUTINE fin2_vector + +END MODULE final_type + +PROGRAM finalizer + IMPLICIT NONE + ! Nothing here +END PROGRAM finalizer + +! TODO: Remove this once finalization is implemented. +! { dg-excess-errors "not yet implemented" } + +! { dg-final { cleanup-modules "final_type" } } diff --git a/gcc/testsuite/gfortran.dg/finalize_8.f03 b/gcc/testsuite/gfortran.dg/finalize_8.f03 new file mode 100644 index 00000000000..6a4a135e0da --- /dev/null +++ b/gcc/testsuite/gfortran.dg/finalize_8.f03 @@ -0,0 +1,37 @@ +! { dg-do compile } + +! Parsing of finalizer procedure definitions. +! Check that FINAL-declarations are only allowed on types defined in the +! specification part of a module. + +MODULE final_type + IMPLICIT NONE + +CONTAINS + + SUBROUTINE bar + IMPLICIT NONE + + TYPE :: mytype + INTEGER, ALLOCATABLE :: fooarr(:) + REAL :: foobar + CONTAINS + FINAL :: myfinal ! { dg-error "in the specification part of a MODULE" } + END TYPE mytype + + CONTAINS + + SUBROUTINE myfinal (el) + TYPE(mytype) :: el + END SUBROUTINE myfinal + + END SUBROUTINE bar + +END MODULE final_type + +PROGRAM finalizer + IMPLICIT NONE + ! Do nothing here +END PROGRAM finalizer + +! { dg-final { cleanup-modules "final_type" } } diff --git a/gcc/testsuite/gfortran.dg/interface_24.f90 b/gcc/testsuite/gfortran.dg/interface_24.f90 new file mode 100644 index 00000000000..1afc5ef2fba --- /dev/null +++ b/gcc/testsuite/gfortran.dg/interface_24.f90 @@ -0,0 +1,66 @@ +! { dg-do compile } +! +! This tests the fix for PR36361: If a function was declared in an INTERFACE +! statement, no attributes may be declared outside of the INTERFACE body. +! +! Contributed by Janus Weil <janus@gcc.gnu.org> + +module m1 + interface + real function f1() + end function + end interface + dimension :: f1(4) ! { dg-error "outside its INTERFACE body" } +end module + + +module m2 + dimension :: f2(4) + interface + real function f2() ! { dg-error "outside its INTERFACE body" } + !end function + end interface +end module + + +! valid +module m3 + interface + real function f3() + dimension :: f3(4) + end function + end interface +end module + + +module m4 + interface + function f4() ! { dg-error "cannot have a deferred shape" } + real :: f4(:) + end function + end interface + allocatable :: f4 ! { dg-error "outside of INTERFACE body" } +end module + + +module m5 + allocatable :: f5(:) + interface + function f5() ! { dg-error "outside its INTERFACE body" } + !real f5(:) + !end function + end interface +end module + + +!valid +module m6 + interface + function f6() + real f6(:) + allocatable :: f6 + end function + end interface +end module + +! { dg-final { cleanup-modules "m1 m2 m3 m4 m5 m6" } } diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c index ef1ebcab4a9..172f1a2f829 100644 --- a/gcc/tree-ssa-coalesce.c +++ b/gcc/tree-ssa-coalesce.c @@ -114,7 +114,7 @@ coalesce_cost_edge (edge e) return MUST_COALESCE_COST; return coalesce_cost (EDGE_FREQUENCY (e), - maybe_hot_bb_p (e->src), + maybe_hot_edge_p (e), EDGE_CRITICAL_P (e)); } diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c index 4dbe7503c9e..93e7810cb3b 100644 --- a/gcc/tree-ssa-ifcombine.c +++ b/gcc/tree-ssa-ifcombine.c @@ -148,8 +148,7 @@ get_name_for_bit_test (tree candidate) { tree def_stmt = SSA_NAME_DEF_STMT (candidate); if (TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT - && (TREE_CODE (GIMPLE_STMT_OPERAND (def_stmt, 1)) == NOP_EXPR - || TREE_CODE (GIMPLE_STMT_OPERAND (def_stmt, 1)) == CONVERT_EXPR)) + && CONVERT_EXPR_P (GIMPLE_STMT_OPERAND (def_stmt, 1))) { tree rhs = GIMPLE_STMT_OPERAND (def_stmt, 1); if (TYPE_PRECISION (TREE_TYPE (rhs)) diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index b6d73ce66f4..0e422146f9b 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -3726,7 +3726,7 @@ find_func_aliases (tree origt) if (TREE_CODE (t) == GIMPLE_MODIFY_STMT) { handle_rhs_call (GIMPLE_STMT_OPERAND (t, 1)); - if (POINTER_TYPE_P (TREE_TYPE (GIMPLE_STMT_OPERAND (t, 1)))) + if (could_have_pointers (GIMPLE_STMT_OPERAND (t, 1))) handle_lhs_call (GIMPLE_STMT_OPERAND (t, 0)); } else diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 65abe270155..d81c6ab7704 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,8 @@ +2008-06-02 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> + + * Makefile.am (mostlyclean-local): Use libtool --mode=clean. + * Makefile.in: Regenerate. + 2008-05-28 Andrew Haley <aph@redhat.com> * java/lang/Class.java (getSimpleName): Use getEnclosingClass(). diff --git a/libjava/Makefile.am b/libjava/Makefile.am index ec05b196c40..559f73ab0d9 100644 --- a/libjava/Makefile.am +++ b/libjava/Makefile.am @@ -372,7 +372,7 @@ DISTCLEANFILES = native.dirs mostlyclean-local: ## Use libtool rm to remove each libtool object - find . -name '*.lo' -print | xargs $(LIBTOOL) rm -f + find . -name '*.lo' -print | xargs $(LIBTOOL) --mode=clean rm -f distclean-local: ## Remove every .d file that was created. diff --git a/libjava/Makefile.in b/libjava/Makefile.in index b2fe1290a0b..ec33ea75912 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -81,7 +81,6 @@ subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/libltdl/acinclude.m4 \ $(top_srcdir)/../config/acx.m4 \ - $(top_srcdir)/../config/confsubdir.m4 \ $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/enable.m4 \ $(top_srcdir)/../config/gxx-include-dir.m4 \ @@ -94,6 +93,7 @@ am__aclocal_m4_deps = $(top_srcdir)/libltdl/acinclude.m4 \ $(top_srcdir)/../config/lib-prefix.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ + $(top_srcdir)/../config/override.m4 \ $(top_srcdir)/../config/proginstall.m4 \ $(top_srcdir)/../config/tls.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ @@ -10311,7 +10311,7 @@ libgcj-tools-$(gcc_version).jar: classpath/tools/tools.zip cp $< $@ mostlyclean-local: - find . -name '*.lo' -print | xargs $(LIBTOOL) rm -f + find . -name '*.lo' -print | xargs $(LIBTOOL) --mode=clean rm -f distclean-local: find . -name '*.d' -print | xargs rm -f diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 614d54c22e8..1132ddd49da 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,20 @@ +2008-06-02 Sandra Loosemore <sandra@codesourcery.com> + Daniel Jacobowitz <dan@codesourcery.com> + + * testsuite/27_io/basic_filebuf/sputbackc/char/9425.cc: Use + dg-require-fileio. + * testsuite/27_io/basic_filebuf/sputbackc/char/1-out.cc: Likewise. + * testsuite/27_io/basic_filebuf/sputbackc/char/2-out.cc: Likewise. + +2008-06-02 Paolo Carlini <paolo.carlini@oracle.com> + + * include/bits/vector.tcc (vector<>::_M_insert_aux): In C++0x mode, + avoid a memory leak if the first __uninitialized_move_a throws. + (vector<>::_M_fill_insert): Do not always copy to __x_copy, similarly + to _M_insert_aux. + * testsuite/23_containers/vector/modifiers/moveable.cc: Adjust. + * testsuite/23_containers/vector/resize/moveable.cc: Likewise. + 2008-05-31 Paolo Carlini <paolo.carlini@oracle.com> Chris Jefferson <chris@bubblescope.net> diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index 030cb3aabcc..462d18f6cbb 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -1,6 +1,6 @@ // Vector implementation (out of line) -*- C++ -*- -// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -305,22 +305,29 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) { const size_type __len = _M_check_len(size_type(1), "vector::_M_insert_aux"); + const size_type __elems_before = __position - begin(); pointer __new_start(this->_M_allocate(__len)); pointer __new_finish(__new_start); try { + // The order of the three operations is dictated by the C++0x + // case, where the moves could alter a new element belonging + // to the existing vector. This is an issue only for callers + // taking the element by const lvalue ref (see 23.1/13). + this->_M_impl.construct(__new_start + __elems_before, #ifdef __GXX_EXPERIMENTAL_CXX0X__ - this->_M_impl.construct(__new_start + (__position - begin()), std::forward<_Args>(__args)...); +#else + __x); #endif + __new_finish = 0; + __new_finish = std::__uninitialized_move_a(this->_M_impl._M_start, __position.base(), __new_start, _M_get_Tp_allocator()); -#ifndef __GXX_EXPERIMENTAL_CXX0X__ - this->_M_impl.construct(__new_finish, __x); -#endif ++__new_finish; + __new_finish = std::__uninitialized_move_a(__position.base(), this->_M_impl._M_finish, @@ -329,7 +336,10 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) } catch(...) { - std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); + if (!__new_finish) + this->_M_impl.destroy(__new_start + __elems_before); + else + std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); _M_deallocate(__new_start, __len); __throw_exception_again; } @@ -351,15 +361,10 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) { if (__n != 0) { -#ifdef __GXX_EXPERIMENTAL_CXX0X__ - value_type __x_copy = __x; -#endif if (size_type(this->_M_impl._M_end_of_storage - this->_M_impl._M_finish) >= __n) { -#ifndef __GXX_EXPERIMENTAL_CXX0X__ value_type __x_copy = __x; -#endif const size_type __elems_after = end() - __position; pointer __old_finish(this->_M_impl._M_finish); if (__elems_after > __n) @@ -392,22 +397,24 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) { const size_type __len = _M_check_len(__n, "vector::_M_fill_insert"); + const size_type __elems_before = __position - begin(); pointer __new_start(this->_M_allocate(__len)); pointer __new_finish(__new_start); try { + // See _M_insert_aux above. + std::__uninitialized_fill_n_a(__new_start + __elems_before, + __n, __x, + _M_get_Tp_allocator()); + __new_finish = 0; + __new_finish = std::__uninitialized_move_a(this->_M_impl._M_start, __position.base(), __new_start, _M_get_Tp_allocator()); -#ifdef __GXX_EXPERIMENTAL_CXX0X__ - std::__uninitialized_fill_n_a(__new_finish, __n, __x_copy, -#else - std::__uninitialized_fill_n_a(__new_finish, __n, __x, -#endif - _M_get_Tp_allocator()); __new_finish += __n; + __new_finish = std::__uninitialized_move_a(__position.base(), this->_M_impl._M_finish, @@ -416,8 +423,13 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD_D) } catch(...) { - std::_Destroy(__new_start, __new_finish, - _M_get_Tp_allocator()); + if (!__new_finish) + std::_Destroy(__new_start + __elems_before, + __new_start + __elems_before + __n, + _M_get_Tp_allocator()); + else + std::_Destroy(__new_start, __new_finish, + _M_get_Tp_allocator()); _M_deallocate(__new_start, __len); __throw_exception_again; } diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc index 15adafc2671..9e466378a62 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable.cc @@ -1,6 +1,6 @@ // { dg-options "-std=gnu++0x" } -// Copyright (C) 2005, 2007 Free Software Foundation, Inc. +// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -104,11 +104,11 @@ test04() std::vector<copycounter> a(10, c); copycounter::copycount = 0; a.insert(a.begin(), 20, c); - VERIFY(copycounter::copycount == 20 + 1); + VERIFY(copycounter::copycount == 20); a.insert(a.end(), 50, c); - VERIFY(copycounter::copycount == 70 + 2); + VERIFY(copycounter::copycount == 70); a.insert(a.begin() + 50, 100, c); - VERIFY(copycounter::copycount == 170 + 3); + VERIFY(copycounter::copycount == 170); } // Test vector::insert(iterator, count, value) makes no unneeded copies diff --git a/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc b/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc index f4dbc19da41..f24babc0792 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc @@ -1,6 +1,6 @@ // { dg-options "-std=gnu++0x" } -// Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. +// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -51,28 +51,28 @@ test01() a.resize(99); a.resize(100); #ifndef _GLIBCXX_DEBUG - VERIFY( copycounter::copycount == 100 + 4 ); + VERIFY( copycounter::copycount == 100 + 1 ); #else - VERIFY( copycounter::copycount == 100 + 4 + 4 ); + VERIFY( copycounter::copycount == 100 + 1 + 4 ); #endif a.resize(99); a.resize(0); #ifndef _GLIBCXX_DEBUG - VERIFY( copycounter::copycount == 100 + 4 ); + VERIFY( copycounter::copycount == 100 + 1 ); #else - VERIFY( copycounter::copycount == 100 + 4 + 6 ); + VERIFY( copycounter::copycount == 100 + 1 + 6 ); #endif a.resize(100); #ifndef _GLIBCXX_DEBUG - VERIFY( copycounter::copycount == 200 + 5 ); + VERIFY( copycounter::copycount == 200 + 2 ); #else - VERIFY( copycounter::copycount == 200 + 5 + 7 ); + VERIFY( copycounter::copycount == 200 + 2 + 7 ); #endif a.clear(); #ifndef _GLIBCXX_DEBUG - VERIFY( copycounter::copycount == 200 + 5 ); + VERIFY( copycounter::copycount == 200 + 2 ); #else - VERIFY( copycounter::copycount == 200 + 5 + 7 ); + VERIFY( copycounter::copycount == 200 + 2 + 7 ); #endif } diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/1-out.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/1-out.cc index 2d89077c1dc..1fc40d7c1cd 100644 --- a/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/1-out.cc +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/1-out.cc @@ -20,6 +20,8 @@ // 27.8.1.4 Overridden virtual functions +// { dg-require-fileio "" } + #include <fstream> #include <testsuite_hooks.h> #include <testsuite_io.h> diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/2-out.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/2-out.cc index 31ecfbd5e26..faf961248e4 100644 --- a/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/2-out.cc +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/2-out.cc @@ -20,6 +20,8 @@ // 27.8.1.4 Overridden virtual functions +// { dg-require-fileio "" } + #include <fstream> #include <testsuite_hooks.h> #include <testsuite_io.h> diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/9425.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/9425.cc index a8465ed4061..2862ef01611 100644 --- a/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/9425.cc +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/sputbackc/char/9425.cc @@ -20,6 +20,8 @@ // 27.8.1.4 Overridden virtual functions +// { dg-require-fileio "" } + #include <fstream> #include <testsuite_hooks.h> |