diff --git a/.compat-gcc-34.metadata b/.compat-gcc-34.metadata new file mode 100644 index 0000000..e77e827 --- /dev/null +++ b/.compat-gcc-34.metadata @@ -0,0 +1 @@ +7c598b47d0d66ecfe188b0f58282849047e728d7 SOURCES/gcc-3.4.6-20060404.tar.bz2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..86bf2af --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/gcc-3.4.6-20060404.tar.bz2 diff --git a/SOURCES/dummylib.sh b/SOURCES/dummylib.sh new file mode 100755 index 0000000..87629c0 --- /dev/null +++ b/SOURCES/dummylib.sh @@ -0,0 +1,46 @@ +#!/bin/sh +if [ $# -lt 3 ]; then echo Usage: dummylib.sh orig_lib_path dummy_lib_path mapfile; exit 1; fi +TMPDIR=`mktemp -d dummylib.sh.XXXXXX` || exit 1 +F=`file -L $1` +C= +S=8 +case "$F" in + *ELF\ 64-bit*shared\ object*x86-64*) C=-m64;; + *ELF\ 32-bit*shared\ object*80?86*) C=-m32; S=4;; + *ELF\ 64-bit*shared\ object*PowerPC*) C=-m64;; + *ELF\ 32-bit*shared\ object*PowerPC*) C=-m32; S=4;; + *ELF\ 64-bit*shared\ object*cisco*) C=-m64;; + *ELF\ 32-bit*shared\ object*cisco*) C=-m32; S=4;; + *ELF\ 64-bit*shared\ object*IA-64*) C=;; + *ELF\ 64-bit*shared\ object*Alpha*) C=;; + *ELF\ 64-bit*shared\ object*390*) C=-m64;; + *ELF\ 32-bit*shared\ object*390*) C=-m31; S=4;; + *ELF\ 64-bit*shared\ object*SPARC*) C=-m64;; + *ELF\ 32-bit*shared\ object*SPARC*) C=-m32; S=4;; + *ELF\ 64-bit*shared\ object*Alpha*) C=;; +esac +readelf -Ws $1 | awk ' +/\.dynsym.* contains/ { start=1 } +/^$/ { start=0 } +/ UND / { next } +/@/ { if (start) { + fn=$8 + intfn="HACK" hack+0 + hack++ + if ($4 ~ /FUNC/) { print ".text"; size=16; print ".type " intfn ",@function" } + else if ($4 ~ /OBJECT/) { print ".data"; size=$3; print ".type " intfn ",@object" } + else if ($4 ~ /NOTYPE/) { print ".data"; size=$3 } + else exit(1); + print ".globl " intfn + if ($5 ~ /WEAK/) { print ".weak " intfn } + else if ($5 !~ /GLOBAL/) exit(1); + print intfn ": .skip " size + print ".size " intfn "," size + print ".symver " intfn "," fn +} } +' > $TMPDIR/lib.s || exit +soname=`readelf -Wd $1 | grep SONAME | sed 's/^.*\[//;s/\].*$//'` +gcc $C -shared -Wl,-soname,$soname,-version-script,$3 \ + -o $2 $TMPDIR/lib.s -nostdlib +strip $2 +rm -rf $TMPDIR diff --git a/SOURCES/gcc34-CVE-2006-3619.patch b/SOURCES/gcc34-CVE-2006-3619.patch new file mode 100644 index 0000000..87e910e --- /dev/null +++ b/SOURCES/gcc34-CVE-2006-3619.patch @@ -0,0 +1,31 @@ +2006-07-17 Richard Guenther + + * jartool.c (extract_jar): Do not allow directory traversal + to parents of the extraction root. + +--- fastjar/jartool.c.jj 2006-07-11 10:53:39.000000000 +0200 ++++ fastjar/jartool.c 2006-07-18 13:49:39.000000000 +0200 +@@ -1736,6 +1736,7 @@ int extract_jar(int fd, char **files, in + const ub1 *start = filename; + char *tmp_buff; + struct stat sbuf; ++ int depth = 0; + + tmp_buff = malloc(sizeof(char) * strlen((const char *)filename)); + +@@ -1756,7 +1757,14 @@ int extract_jar(int fd, char **files, in + #ifdef DEBUG + printf("checking the existance of %s\n", tmp_buff); + #endif +- ++ if(strcmp(tmp_buff, "..") == 0){ ++ --depth; ++ if (depth < 0){ ++ fprintf(stderr, "Traversal to parent directories during unpacking!\n"); ++ exit(1); ++ } ++ } else if (strcmp(tmp_buff, ".") != 0) ++ ++depth; + if(stat(tmp_buff, &sbuf) < 0){ + if(errno != ENOENT){ + perror("stat"); diff --git a/SOURCES/gcc34-CXXABI131.patch b/SOURCES/gcc34-CXXABI131.patch new file mode 100644 index 0000000..1a11edd --- /dev/null +++ b/SOURCES/gcc34-CXXABI131.patch @@ -0,0 +1,47 @@ +2005-02-18 Richard Henderson + + PR libstdc++/10606 + * config/linker-map.gnu (CXXABI_1.3.1): Add __cxa_get_exception_ptr. + * libsupc++/eh_catch.cc (__cxa_get_exception_ptr): New. + * libsupc++/unwind-cxx.h (__cxa_get_exception_ptr): Declare. + +--- libstdc++-v3/config/linker-map.gnu (revision 94498) ++++ libstdc++-v3/config/linker-map.gnu (revision 95705) +@@ -406,3 +410,9 @@ CXXABI_1.3 { + local: + *; + }; ++ ++CXXABI_1.3.1 { ++ ++ __cxa_get_exception_ptr; ++ ++} CXXABI_1.3; +--- libstdc++-v3/libsupc++/unwind-cxx.h (revision 94498) ++++ libstdc++-v3/libsupc++/unwind-cxx.h (revision 95705) +@@ -107,6 +107,7 @@ extern "C" void __cxa_throw (void *throw + __attribute__((noreturn)); + + // Used to implement exception handlers. ++extern "C" void *__cxa_get_exception_ptr (void *) throw(); + extern "C" void *__cxa_begin_catch (void *) throw(); + extern "C" void __cxa_end_catch (); + extern "C" void __cxa_rethrow () __attribute__((noreturn)); +--- libstdc++-v3/libsupc++/eh_catch.cc (revision 94498) ++++ libstdc++-v3/libsupc++/eh_catch.cc (revision 95705) +@@ -33,6 +33,15 @@ + + using namespace __cxxabiv1; + ++extern "C" void * ++__cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) throw() ++{ ++ _Unwind_Exception *exceptionObject ++ = reinterpret_cast <_Unwind_Exception *>(exc_obj_in); ++ __cxa_exception *header = __get_exception_header_from_ue (exceptionObject); ++ ++ return header->adjustedPtr; ++} + + extern "C" void * + __cxa_begin_catch (void *exc_obj_in) throw() diff --git a/SOURCES/gcc34-bison4.patch b/SOURCES/gcc34-bison4.patch new file mode 100644 index 0000000..f4a388f --- /dev/null +++ b/SOURCES/gcc34-bison4.patch @@ -0,0 +1,35 @@ +--- gcc/c-parse.in 2009-02-10 12:41:09.000000000 +0100 ++++ gcc/c-parse.in 2009-02-10 13:23:53.000000000 +0100 +@@ -1647,7 +1647,7 @@ enum_head: + + structsp_attr: + struct_head identifier '{' +- { $$ = start_struct (RECORD_TYPE, $2); ++ { $$ = start_struct (RECORD_TYPE, $2); + /* Start scope of tag before parsing components. */ + } + component_decl_list '}' maybe_attribute +@@ -1658,7 +1658,7 @@ structsp_attr: + nreverse ($3), chainon ($1, $5)); + } + | union_head identifier '{' +- { $$ = start_struct (UNION_TYPE, $2); } ++ { $$ = start_struct (UNION_TYPE, $2); } + component_decl_list '}' maybe_attribute + { $$ = finish_struct ($4, nreverse ($5), + chainon ($1, $7)); } +@@ -1667,12 +1667,12 @@ structsp_attr: + nreverse ($3), chainon ($1, $5)); + } + | enum_head identifier '{' +- { $$ = start_enum ($2); } ++ { $$ = start_enum ($2); } + enumlist maybecomma_warn '}' maybe_attribute + { $$ = finish_enum ($4, nreverse ($5), + chainon ($1, $8)); } + | enum_head '{' +- { $$ = start_enum (NULL_TREE); } ++ { $$ = start_enum (NULL_TREE); } + enumlist maybecomma_warn '}' maybe_attribute + { $$ = finish_enum ($3, nreverse ($4), + chainon ($1, $7)); } diff --git a/SOURCES/gcc34-dwarf2-frame_base.patch b/SOURCES/gcc34-dwarf2-frame_base.patch new file mode 100644 index 0000000..7458d82 --- /dev/null +++ b/SOURCES/gcc34-dwarf2-frame_base.patch @@ -0,0 +1,1153 @@ +2005-08-22 Richard Henderson + + * function.c (ARG_POINTER_CFA_OFFSET): Move ... + * defaults.h (ARG_POINTER_CFA_OFFSET): ... here. + (INCOMING_FRAME_SP_OFFSET): Moved from ... + * dwarf2out.c (INCOMING_FRAME_SP_OFFSET): ... here. + (struct cfa_loc): Change reg to unsigned int, + rearrange for better packing. + (lookup_cfa_1): Remove inline marker. + (cfa_equal_p): Split out of ... + (def_cfa_1): ... here. Use INVALID_REGNUM. + (build_cfa_loc): Handle !cfa->indirect. + (frame_pointer_cfa_offset): New. + (dbx_reg_number): Assert register elimination performed; do + leaf register remapping. + (reg_loc_descriptor): Avoid calling dbx_reg_number when unused. + (eliminate_reg_to_offset): New. + (based_loc_descr): Remove can_use_fbreg argument. Use fbreg only + for verifiably local stack frame addresses; re-base to CFA. + (mem_loc_descriptor): Remove can_use_fbreg argument. + (concat_loc_descriptor, loc_descriptor): Likewise. + (containing_function_has_frame_base): Remove. + (rtl_for_decl_location): Don't do register elimination or + leaf register remapping here. + (secname_for_decl): Split out from .. + (add_location_or_const_value_attribute): ... here. + (convert_cfa_to_loc_list): New. + (compute_frame_pointer_to_cfa_displacement): New. + (gen_subprogram_die): Use them. + * tree.h (frame_base_decl): Remove. + * var-tracking.c (frame_base_decl, frame_stack_adjust): Remove. + (prologue_stack_adjust): Remove. + (vt_stack_adjustments): Use INCOMING_FRAME_SP_OFFSET. + (adjust_stack_reference): Re-base memories to arg_pointer_rtx. + (set_frame_base_location): Remove. + (compute_bb_dataflow, emit_notes_in_bb): Don't call it. + (dump_attrs_list, dump_dataflow_set): Use string concatenation. + (vt_add_function_parameters): Don't eliminate_regs. + (vt_initialize): Don't create frame_base_decl. + +--- gcc/defaults.h.orig 2005-11-17 23:01:55.000000000 -0200 ++++ gcc/defaults.h 2005-11-17 23:07:55.000000000 -0200 +@@ -715,4 +715,15 @@ + #define EXIT_IGNORE_STACK 0 + #endif + ++/* On most machines, the CFA coincides with the first incoming parm. */ ++#ifndef ARG_POINTER_CFA_OFFSET ++#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL) ++#endif ++ ++/* The offset from the incoming value of %sp to the top of the stack frame ++ for the current function. */ ++#ifndef INCOMING_FRAME_SP_OFFSET ++#define INCOMING_FRAME_SP_OFFSET 0 ++#endif ++ + #endif /* ! GCC_DEFAULTS_H */ +--- gcc/dwarf2out.c.orig 2005-11-17 23:07:20.000000000 -0200 ++++ gcc/dwarf2out.c 2005-11-17 23:07:55.000000000 -0200 +@@ -228,9 +228,9 @@ dw_cfi_node; + of this structure. */ + typedef struct cfa_loc GTY(()) + { +- unsigned long reg; + HOST_WIDE_INT offset; + HOST_WIDE_INT base_offset; ++ unsigned int reg; + int indirect; /* 1 if CFA is accessed via a dereference. */ + } dw_cfa_location; + +@@ -418,12 +418,6 @@ static void def_cfa_1 (const char *, dw_ + #ifndef DWARF_FRAME_REGNUM + #define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) + #endif +- +-/* The offset from the incoming value of %sp to the top of the stack frame +- for the current function. */ +-#ifndef INCOMING_FRAME_SP_OFFSET +-#define INCOMING_FRAME_SP_OFFSET 0 +-#endif + + /* Hook used by __throw. */ + +@@ -651,7 +645,7 @@ add_fde_cfi (const char *label, dw_cfi_r + + /* Subroutine of lookup_cfa. */ + +-static inline void ++static void + lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc) + { + switch (cfi->dw_cfi_opc) +@@ -681,7 +675,7 @@ lookup_cfa (dw_cfa_location *loc) + { + dw_cfi_ref cfi; + +- loc->reg = (unsigned long) -1; ++ loc->reg = INVALID_REGNUM; + loc->offset = 0; + loc->indirect = 0; + loc->base_offset = 0; +@@ -725,6 +719,18 @@ dwarf2out_def_cfa (const char *label, un + def_cfa_1 (label, &loc); + } + ++/* Determine if two dw_cfa_location structures define the same data. */ ++ ++static bool ++cfa_equal_p (const dw_cfa_location *loc1, const dw_cfa_location *loc2) ++{ ++ return (loc1->reg == loc2->reg ++ && loc1->offset == loc2->offset ++ && loc1->indirect == loc2->indirect ++ && (loc1->indirect == 0 ++ || loc1->base_offset == loc2->base_offset)); ++} ++ + /* This routine does the actual work. The CFA is now calculated from + the dw_cfa_location structure. */ + +@@ -744,9 +750,7 @@ def_cfa_1 (const char *label, dw_cfa_loc + lookup_cfa (&old_cfa); + + /* If nothing changed, no need to issue any call frame instructions. */ +- if (loc.reg == old_cfa.reg && loc.offset == old_cfa.offset +- && loc.indirect == old_cfa.indirect +- && (loc.indirect == 0 || loc.base_offset == old_cfa.base_offset)) ++ if (cfa_equal_p (&loc, &old_cfa)) + return; + + cfi = new_cfi (); +@@ -761,7 +765,8 @@ def_cfa_1 (const char *label, dw_cfa_loc + } + + #ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */ +- else if (loc.offset == old_cfa.offset && old_cfa.reg != (unsigned long) -1 ++ else if (loc.offset == old_cfa.offset ++ && old_cfa.reg != INVALID_REGNUM + && !loc.indirect) + { + /* Construct a "DW_CFA_def_cfa_register " instruction, +@@ -3098,28 +3103,40 @@ build_cfa_loc (dw_cfa_location *cfa) + { + struct dw_loc_descr_struct *head, *tmp; + +- if (cfa->indirect == 0) +- abort (); +- +- if (cfa->base_offset) ++ if (cfa->indirect) + { +- if (cfa->reg <= 31) +- head = new_loc_descr (DW_OP_breg0 + cfa->reg, cfa->base_offset, 0); ++ if (cfa->base_offset) ++ { ++ if (cfa->reg <= 31) ++ head = new_loc_descr (DW_OP_breg0 + cfa->reg, cfa->base_offset, 0); ++ else ++ head = new_loc_descr (DW_OP_bregx, cfa->reg, cfa->base_offset); ++ } ++ else if (cfa->reg <= 31) ++ head = new_loc_descr (DW_OP_reg0 + cfa->reg, 0, 0); + else +- head = new_loc_descr (DW_OP_bregx, cfa->reg, cfa->base_offset); ++ head = new_loc_descr (DW_OP_regx, cfa->reg, 0); ++ ++ head->dw_loc_oprnd1.val_class = dw_val_class_const; ++ tmp = new_loc_descr (DW_OP_deref, 0, 0); ++ add_loc_descr (&head, tmp); ++ if (cfa->offset != 0) ++ { ++ tmp = new_loc_descr (DW_OP_plus_uconst, cfa->offset, 0); ++ add_loc_descr (&head, tmp); ++ } + } +- else if (cfa->reg <= 31) +- head = new_loc_descr (DW_OP_reg0 + cfa->reg, 0, 0); + else +- head = new_loc_descr (DW_OP_regx, cfa->reg, 0); +- +- head->dw_loc_oprnd1.val_class = dw_val_class_const; +- tmp = new_loc_descr (DW_OP_deref, 0, 0); +- add_loc_descr (&head, tmp); +- if (cfa->offset != 0) + { +- tmp = new_loc_descr (DW_OP_plus_uconst, cfa->offset, 0); +- add_loc_descr (&head, tmp); ++ if (cfa->offset == 0) ++ if (cfa->reg <= 31) ++ head = new_loc_descr (DW_OP_reg0 + cfa->reg, 0, 0); ++ else ++ head = new_loc_descr (DW_OP_regx, cfa->reg, 0); ++ else if (cfa->reg <= 31) ++ head = new_loc_descr (DW_OP_breg0 + cfa->reg, cfa->offset, 0); ++ else ++ head = new_loc_descr (DW_OP_bregx, cfa->reg, cfa->offset); + } + + return head; +@@ -3607,6 +3624,10 @@ static GTY(()) int label_num; + + #ifdef DWARF2_DEBUGGING_INFO + ++/* Offset from the "steady-state frame pointer" to the CFA, ++ within the current function. */ ++static HOST_WIDE_INT frame_pointer_cfa_offset; ++ + /* Forward declarations for functions defined in this file. */ + + static int is_pseudo_reg (rtx); +@@ -3752,11 +3773,11 @@ static dw_loc_descr_ref reg_loc_descript + static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int); + static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx); + static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT); +-static dw_loc_descr_ref based_loc_descr (unsigned, HOST_WIDE_INT, bool); ++static dw_loc_descr_ref based_loc_descr (rtx, HOST_WIDE_INT); + static int is_based_loc (rtx); +-static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode, bool); +-static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx, bool); +-static dw_loc_descr_ref loc_descriptor (rtx, bool); ++static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode); ++static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx); ++static dw_loc_descr_ref loc_descriptor (rtx); + static dw_loc_descr_ref loc_descriptor_from_tree (tree, int); + static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int); + static tree field_type (tree); +@@ -8171,9 +8192,20 @@ dbx_reg_number (rtx rtl) + { + unsigned regno = REGNO (rtl); + ++ if (! (HARD_FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM ++ || rtl != arg_pointer_rtx)) ++ abort (); ++ if (! (HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM ++ || rtl != frame_pointer_rtx)) ++ abort (); ++ + if (regno >= FIRST_PSEUDO_REGISTER) + abort (); + ++#ifdef LEAF_REG_REMAP ++ regno = LEAF_REG_REMAP (regno); ++#endif ++ + return DBX_REGISTER_NUMBER (regno); + } + +@@ -8203,20 +8235,17 @@ add_loc_descr_op_piece (dw_loc_descr_ref + static dw_loc_descr_ref + reg_loc_descriptor (rtx rtl) + { +- unsigned reg; + rtx regs; + + if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER) + return 0; + +- reg = dbx_reg_number (rtl); + regs = (*targetm.dwarf_register_span) (rtl); + +- if (HARD_REGNO_NREGS (REGNO (rtl), GET_MODE (rtl)) > 1 +- || regs) ++ if (HARD_REGNO_NREGS(REGNO (rtl), GET_MODE (rtl)) > 1 || regs) + return multiple_reg_loc_descriptor (rtl, regs); + else +- return one_reg_loc_descriptor (reg); ++ return one_reg_loc_descriptor (dbx_reg_number (rtl)); + } + + /* Return a location descriptor that designates a machine register for +@@ -8321,25 +8350,54 @@ int_loc_descriptor (HOST_WIDE_INT i) + return new_loc_descr (op, i, 0); + } + ++/* Return an offset from an eliminable register to the post-prologue ++ frame pointer. */ ++ ++static HOST_WIDE_INT ++eliminate_reg_to_offset (rtx reg) ++{ ++ HOST_WIDE_INT offset = 0; ++ ++ reg = eliminate_regs (reg, VOIDmode, NULL_RTX); ++ if (GET_CODE (reg) == PLUS) ++ { ++ offset = INTVAL (XEXP (reg, 1)); ++ reg = XEXP (reg, 0); ++ } ++ if (! (reg == (frame_pointer_needed ? hard_frame_pointer_rtx ++ : stack_pointer_rtx))) ++ abort (); ++ ++ return offset; ++} ++ + /* Return a location descriptor that designates a base+offset location. */ + + static dw_loc_descr_ref +-based_loc_descr (unsigned int reg, HOST_WIDE_INT offset, bool can_use_fbreg) ++based_loc_descr (rtx reg, HOST_WIDE_INT offset) + { + dw_loc_descr_ref loc_result; +- /* For the "frame base", we use the frame pointer or stack pointer +- registers, since the RTL for local variables is relative to one of +- them. */ +- unsigned fp_reg = DBX_REGISTER_NUMBER (frame_pointer_needed +- ? HARD_FRAME_POINTER_REGNUM +- : STACK_POINTER_REGNUM); +- +- if (reg == fp_reg && can_use_fbreg) +- loc_result = new_loc_descr (DW_OP_fbreg, offset, 0); +- else if (reg <= 31) +- loc_result = new_loc_descr (DW_OP_breg0 + reg, offset, 0); ++ ++ /* We only use "frame base" when we're sure we're talking about the ++ post-prologue local stack frame. We do this by *not* running ++ register elimination until this point, and recognizing the special ++ argument pointer and soft frame pointer rtx's. */ ++ if (reg == arg_pointer_rtx || reg == frame_pointer_rtx) ++ { ++ offset += eliminate_reg_to_offset (reg); ++ offset += frame_pointer_cfa_offset; ++ ++ loc_result = new_loc_descr (DW_OP_fbreg, offset, 0); ++ } + else +- loc_result = new_loc_descr (DW_OP_bregx, reg, offset); ++ { ++ unsigned int regno = dbx_reg_number (reg); ++ ++ if (regno <= 31) ++ loc_result = new_loc_descr (DW_OP_breg0 + regno, offset, 0); ++ else ++ loc_result = new_loc_descr (DW_OP_bregx, regno, offset); ++ } + + return loc_result; + } +@@ -8368,15 +8426,13 @@ is_based_loc (rtx rtl) + MODE is the mode of the memory reference, needed to handle some + autoincrement addressing modes. + +- CAN_USE_FBREG is a flag whether we can use DW_AT_frame_base in the location +- list for RTL. We can't use it when we are emitting location list for +- virtual variable frame_base_decl (i.e. a location list for DW_AT_frame_base) +- which describes how frame base changes when !frame_pointer_needed. ++ CAN_USE_FBREG is a flag whether we can use DW_AT_frame_base in the ++ location list for RTL. + + Return 0 if we can't represent the location. */ + + static dw_loc_descr_ref +-mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg) ++mem_loc_descriptor (rtx rtl, enum machine_mode mode) + { + dw_loc_descr_ref mem_loc_result = NULL; + +@@ -8422,13 +8478,11 @@ mem_loc_descriptor (rtx rtl, enum machin + memory) so DWARF consumers need to be aware of the subtle + distinction between OP_REG and OP_BASEREG. */ + if (REGNO (rtl) < FIRST_PSEUDO_REGISTER) +- mem_loc_result = based_loc_descr (dbx_reg_number (rtl), 0, +- can_use_fbreg); ++ mem_loc_result = based_loc_descr (rtl, 0); + break; + + case MEM: +- mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl), +- can_use_fbreg); ++ mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); + if (mem_loc_result != 0) + add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_deref, 0, 0)); + break; +@@ -8494,13 +8548,11 @@ mem_loc_descriptor (rtx rtl, enum machin + case PLUS: + plus: + if (is_based_loc (rtl)) +- mem_loc_result = based_loc_descr (dbx_reg_number (XEXP (rtl, 0)), +- INTVAL (XEXP (rtl, 1)), +- can_use_fbreg); ++ mem_loc_result = based_loc_descr (XEXP (rtl, 0), ++ INTVAL (XEXP (rtl, 1))); + else + { +- mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode, +- can_use_fbreg); ++ mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode); + if (mem_loc_result == 0) + break; + +@@ -8512,8 +8564,7 @@ mem_loc_descriptor (rtx rtl, enum machin + else + { + add_loc_descr (&mem_loc_result, +- mem_loc_descriptor (XEXP (rtl, 1), mode, +- can_use_fbreg)); ++ mem_loc_descriptor (XEXP (rtl, 1), mode)); + add_loc_descr (&mem_loc_result, + new_loc_descr (DW_OP_plus, 0, 0)); + } +@@ -8524,10 +8575,8 @@ mem_loc_descriptor (rtx rtl, enum machin + { + /* If a pseudo-reg is optimized away, it is possible for it to + be replaced with a MEM containing a multiply. */ +- dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, +- can_use_fbreg); +- dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode, +- can_use_fbreg); ++ dw_loc_descr_ref op0 = mem_loc_descriptor (XEXP (rtl, 0), mode); ++ dw_loc_descr_ref op1 = mem_loc_descriptor (XEXP (rtl, 1), mode); + + if (op0 == 0 || op1 == 0) + break; +@@ -8546,8 +8595,7 @@ mem_loc_descriptor (rtx rtl, enum machin + /* If this is a MEM, return its address. Otherwise, we can't + represent this. */ + if (GET_CODE (XEXP (rtl, 0)) == MEM) +- return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode, +- can_use_fbreg); ++ return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode); + else + return 0; + +@@ -8562,11 +8610,11 @@ mem_loc_descriptor (rtx rtl, enum machin + This is typically a complex variable. */ + + static dw_loc_descr_ref +-concat_loc_descriptor (rtx x0, rtx x1, bool can_use_fbreg) ++concat_loc_descriptor (rtx x0, rtx x1) + { + dw_loc_descr_ref cc_loc_result = NULL; +- dw_loc_descr_ref x0_ref = loc_descriptor (x0, can_use_fbreg); +- dw_loc_descr_ref x1_ref = loc_descriptor (x1, can_use_fbreg); ++ dw_loc_descr_ref x0_ref = loc_descriptor (x0); ++ dw_loc_descr_ref x1_ref = loc_descriptor (x1); + + if (x0_ref == 0 || x1_ref == 0) + return 0; +@@ -8580,29 +8628,6 @@ concat_loc_descriptor (rtx x0, rtx x1, b + return cc_loc_result; + } + +-/* Return true if DECL's containing function has a frame base attribute. +- Return false otherwise. */ +- +-static bool +-containing_function_has_frame_base (tree decl) +-{ +- tree declcontext = decl_function_context (decl); +- dw_die_ref context; +- dw_attr_ref attr; +- +- if (!declcontext) +- return false; +- +- context = lookup_decl_die (declcontext); +- if (!context) +- return false; +- +- for (attr = context->die_attr; attr; attr = attr->dw_attr_next) +- if (attr->dw_attr == DW_AT_frame_base) +- return true; +- return false; +-} +- + /* Output a proper Dwarf location descriptor for a variable or parameter + which is either allocated in a register or in a memory location. For a + register, we just generate an OP_REG and the register number. For a +@@ -8612,7 +8637,7 @@ containing_function_has_frame_base (tree + If we don't know how to describe it, return 0. */ + + static dw_loc_descr_ref +-loc_descriptor (rtx rtl, bool can_use_fbreg) ++loc_descriptor (rtx rtl) + { + dw_loc_descr_ref loc_result = NULL; + +@@ -8633,20 +8658,18 @@ loc_descriptor (rtx rtl, bool can_use_fb + break; + + case MEM: +- loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl), +- can_use_fbreg); ++ loc_result = mem_loc_descriptor (XEXP (rtl, 0), GET_MODE (rtl)); + break; + + case CONCAT: +- loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1), +- can_use_fbreg); ++ loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1)); + break; + + case VAR_LOCATION: + /* Single part. */ + if (GET_CODE (XEXP (rtl, 1)) != PARALLEL) + { +- loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0), can_use_fbreg); ++ loc_result = loc_descriptor (XEXP (XEXP (rtl, 1), 0)); + } + /* Multiple parts. */ + else +@@ -8657,16 +8680,14 @@ loc_descriptor (rtx rtl, bool can_use_fb + int i; + + /* Create the first one, so we have something to add to. */ +- loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), +- can_use_fbreg); ++ loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0)); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); + add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode)); + for (i = 1; i < num_elem; i++) + { + dw_loc_descr_ref temp; + +- temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), +- can_use_fbreg); ++ temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0)); + add_loc_descr (&loc_result, temp); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); + add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode)); +@@ -8789,7 +8810,6 @@ loc_descriptor_from_tree (tree loc, int + else + { + enum machine_mode mode = GET_MODE (rtl); +- bool can_use_fb = containing_function_has_frame_base (loc); + + if (GET_CODE (rtl) == MEM) + { +@@ -8797,7 +8817,7 @@ loc_descriptor_from_tree (tree loc, int + rtl = XEXP (rtl, 0); + } + +- ret = mem_loc_descriptor (rtl, mode, can_use_fb); ++ ret = mem_loc_descriptor (rtl, mode); + } + } + break; +@@ -8872,18 +8892,16 @@ loc_descriptor_from_tree (tree loc, int + /* Get an RTL for this, if something has been emitted. */ + rtx rtl = lookup_constant_def (loc); + enum machine_mode mode; +- bool can_use_fb; + + if (GET_CODE (rtl) != MEM) + return 0; +- can_use_fb = containing_function_has_frame_base (loc); + mode = GET_MODE (rtl); + rtl = XEXP (rtl, 0); + + rtl = (*targetm.delegitimize_address) (rtl); + + indirect_p = 1; +- ret = mem_loc_descriptor (rtl, mode, can_use_fb); ++ ret = mem_loc_descriptor (rtl, mode); + break; + } + +@@ -9743,19 +9761,10 @@ rtl_for_decl_location (tree decl) + } + } + +- if (rtl != NULL_RTX) +- { +- rtl = eliminate_regs (rtl, 0, NULL_RTX); +-#ifdef LEAF_REG_REMAP +- if (current_function_uses_only_leaf_regs) +- leaf_renumber_regs_insn (rtl); +-#endif +- } +- + /* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time constant, + and will have been substituted directly into all expressions that use it. + C does not have such a concept, but C++ and other languages do. */ +- else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl)) ++ if (!rtl && TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl)) + { + /* If a variable is initialized with a string constant without embedded + zeros, build CONST_STRING. */ +@@ -9803,6 +9812,34 @@ rtl_for_decl_location (tree decl) + return rtl; + } + ++/* We need to figure out what section we should use as the base for the ++ address ranges where a given location is valid. ++ 1. If this particular DECL has a section associated with it, use that. ++ 2. If this function has a section associated with it, use that. ++ 3. Otherwise, use the text section. ++ XXX: If you split a variable across multiple sections, we won't notice. */ ++ ++static const char * ++secname_for_decl (tree decl) ++{ ++ const char *secname; ++ ++ if (DECL_SECTION_NAME (decl)) ++ { ++ tree sectree = DECL_SECTION_NAME (decl); ++ secname = TREE_STRING_POINTER (sectree); ++ } ++ else if (current_function_decl && DECL_SECTION_NAME (current_function_decl)) ++ { ++ tree sectree = DECL_SECTION_NAME (current_function_decl); ++ secname = TREE_STRING_POINTER (sectree); ++ } ++ else ++ secname = text_section_label; ++ ++ return secname; ++} ++ + /* Generate *either* a DW_AT_location attribute or else a DW_AT_const_value + data attribute for a variable or a parameter. We generate the + DW_AT_const_value attribute only in those cases where the given variable +@@ -9834,36 +9871,11 @@ add_location_or_const_value_attribute (d + differ. */ + if (loc_list && loc_list->first != loc_list->last) + { +- const char *secname; +- const char *endname; ++ const char *secname, *endname; + dw_loc_list_ref list; + rtx varloc; + struct var_loc_node *node; + +- /* We need to figure out what section we should use as the base +- for the address ranges where a given location is valid. +- 1. If this particular DECL has a section associated with it, +- use that. +- 2. If this function has a section associated with it, use +- that. +- 3. Otherwise, use the text section. +- XXX: If you split a variable across multiple sections, this +- won't notice. */ +- +- if (DECL_SECTION_NAME (decl)) +- { +- tree sectree = DECL_SECTION_NAME (decl); +- secname = TREE_STRING_POINTER (sectree); +- } +- else if (current_function_decl +- && DECL_SECTION_NAME (current_function_decl)) +- { +- tree sectree = DECL_SECTION_NAME (current_function_decl); +- secname = TREE_STRING_POINTER (sectree); +- } +- else +- secname = text_section_label; +- + /* Now that we know what section we are using for a base, + actually construct the list of locations. + The first location information is what is passed to the +@@ -9877,7 +9889,9 @@ add_location_or_const_value_attribute (d + + node = loc_list->first; + varloc = NOTE_VAR_LOCATION (node->var_loc_note); +- list = new_loc_list (loc_descriptor (varloc, attr != DW_AT_frame_base), ++ secname = secname_for_decl (decl); ++ ++ list = new_loc_list (loc_descriptor (varloc), + node->label, node->next->label, secname, 1); + node = node->next; + +@@ -9888,8 +9902,7 @@ add_location_or_const_value_attribute (d + NODE->NEXT->LABEL. */ + varloc = NOTE_VAR_LOCATION (node->var_loc_note); + add_loc_descr_to_loc_list (&list, +- loc_descriptor (varloc, +- attr != DW_AT_frame_base), ++ loc_descriptor (varloc), + node->label, node->next->label, secname); + } + +@@ -9909,8 +9922,7 @@ add_location_or_const_value_attribute (d + endname = ggc_strdup (label_id); + } + add_loc_descr_to_loc_list (&list, +- loc_descriptor (varloc, +- attr != DW_AT_frame_base), ++ loc_descriptor (varloc), + node->label, endname, secname); + } + +@@ -9964,7 +9976,7 @@ add_location_or_const_value_attribute (d + case REG: + case SUBREG: + case CONCAT: +- descr = loc_descriptor (rtl, true); ++ descr = loc_descriptor (rtl); + } + add_AT_location_description (die, attr, descr); + break; +@@ -9977,14 +9989,14 @@ add_location_or_const_value_attribute (d + int i; + + /* Create the first one, so we have something to add to. */ +- descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), true); ++ descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0)); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); + add_loc_descr_op_piece (&descr, GET_MODE_SIZE (mode)); + for (i = 1; i < num_elem; i++) + { + dw_loc_descr_ref temp; + +- temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), true); ++ temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0)); + add_loc_descr (&descr, temp); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); + add_loc_descr_op_piece (&descr, GET_MODE_SIZE (mode)); +@@ -10030,6 +10042,98 @@ tree_add_const_value_attribute (dw_die_r + } + } + ++/* Convert the CFI instructions for the current function into a location ++ list. This is used for DW_AT_frame_base when we targeting a dwarf2 ++ consumer that does not support the dwarf3 DW_OP_call_frame_cfa. */ ++ ++static dw_loc_list_ref ++convert_cfa_to_loc_list (void) ++{ ++ dw_fde_ref fde; ++ dw_loc_list_ref list, *list_tail; ++ dw_cfi_ref cfi; ++ dw_cfa_location last_cfa, next_cfa; ++ const char *start_label, *last_label, *section; ++ ++ fde = &fde_table[fde_table_in_use - 1]; ++ ++ section = secname_for_decl (current_function_decl); ++ list_tail = &list; ++ list = NULL; ++ ++ next_cfa.reg = INVALID_REGNUM; ++ next_cfa.offset = 0; ++ next_cfa.indirect = 0; ++ next_cfa.base_offset = 0; ++ ++ start_label = fde->dw_fde_begin; ++ ++ /* ??? Bald assumption that the CIE opcode list does not contain ++ advance opcodes. */ ++ for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next) ++ lookup_cfa_1 (cfi, &next_cfa); ++ ++ last_cfa = next_cfa; ++ last_label = start_label; ++ ++ for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next) ++ switch (cfi->dw_cfi_opc) ++ { ++ case DW_CFA_advance_loc1: ++ case DW_CFA_advance_loc2: ++ case DW_CFA_advance_loc4: ++ if (!cfa_equal_p (&last_cfa, &next_cfa)) ++ { ++ *list_tail = new_loc_list (build_cfa_loc (&last_cfa), start_label, ++ last_label, section, list == NULL); ++ ++ list_tail = &(*list_tail)->dw_loc_next; ++ last_cfa = next_cfa; ++ start_label = last_label; ++ } ++ last_label = cfi->dw_cfi_oprnd1.dw_cfi_addr; ++ break; ++ ++ case DW_CFA_advance_loc: ++ /* The encoding is complex enough that we should never emit this. */ ++ case DW_CFA_remember_state: ++ case DW_CFA_restore_state: ++ /* We don't handle these two in this function. It would be possible ++ if it were to be required. */ ++ abort (); ++ ++ default: ++ lookup_cfa_1 (cfi, &next_cfa); ++ break; ++ } ++ ++ if (!cfa_equal_p (&last_cfa, &next_cfa)) ++ { ++ *list_tail = new_loc_list (build_cfa_loc (&last_cfa), start_label, ++ last_label, section, list == NULL); ++ list_tail = &(*list_tail)->dw_loc_next; ++ start_label = last_label; ++ } ++ *list_tail = new_loc_list (build_cfa_loc (&next_cfa), start_label, ++ fde->dw_fde_end, section, list == NULL); ++ ++ return list; ++} ++ ++/* Compute a displacement from the "steady-state frame pointer" to ++ the CFA, and store it in frame_pointer_cfa_offset. */ ++ ++static void ++compute_frame_pointer_to_cfa_displacement (void) ++{ ++ HOST_WIDE_INT offset; ++ ++ offset = eliminate_reg_to_offset (arg_pointer_rtx); ++ offset += ARG_POINTER_CFA_OFFSET (current_function_decl); ++ ++ frame_pointer_cfa_offset = -offset; ++} ++ + /* Generate a DW_AT_name attribute given some string value to be included as + the value of the attribute. */ + +@@ -10128,7 +10232,7 @@ add_bound_info (dw_die_ref subrange_die, + add_AT_flag (decl_die, DW_AT_artificial, 1); + add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx); + add_AT_location_description (decl_die, DW_AT_location, +- loc_descriptor (loc, true)); ++ loc_descriptor (loc)); + add_AT_die_ref (subrange_die, bound_attr, decl_die); + } + +@@ -11114,7 +11218,6 @@ gen_subprogram_die (tree decl, dw_die_re + char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; + tree origin = decl_ultimate_origin (decl); + dw_die_ref subr_die; +- rtx fp_reg; + tree fn_arg_types; + tree outer_scope; + dw_die_ref old_die = lookup_decl_die (decl); +@@ -11277,20 +11380,32 @@ gen_subprogram_die (tree decl, dw_die_re + add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde); + #endif + +- /* Define the "frame base" location for this routine. We use the +- frame pointer or stack pointer registers, since the RTL for local +- variables is relative to one of them. */ +- if (frame_base_decl && lookup_decl_loc (frame_base_decl) != NULL) +- { +- add_location_or_const_value_attribute (subr_die, frame_base_decl, +- DW_AT_frame_base); +- } +- else +- { +- fp_reg +- = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; +- add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); +- } ++ /* We define the "frame base" as the function's CFA. This is more ++ convenient for several reasons: (1) It's stable across the prologue ++ and epilogue, which makes it better than just a frame pointer, ++ (2) With dwarf3, there exists a one-byte encoding that allows us ++ to reference the .debug_frame data by proxy, but failing that, ++ (3) We can at least reuse the code inspection and interpretation ++ code that determines the CFA position at various points in the ++ function. */ ++ /* ??? Use some command-line or configury switch to enable the use ++ of dwarf3 DW_OP_call_frame_cfa. At present there are no dwarf ++ consumers that understand it; fall back to "pure" dwarf2 and ++ convert the CFA data into a location list. */ ++ { ++ dw_loc_list_ref list = convert_cfa_to_loc_list (); ++ if (list->dw_loc_next) ++ add_AT_loc_list (subr_die, DW_AT_frame_base, list); ++ else ++ add_AT_loc (subr_die, DW_AT_frame_base, list->expr); ++ } ++ ++ /* Compute a displacement from the "steady-state frame pointer" to ++ the CFA. The former is what all stack slots and argument slots ++ will reference in the rtl; the later is what we've told the ++ debugger about. We'll need to adjust all frame_base references ++ by this displacement. */ ++ compute_frame_pointer_to_cfa_displacement (); + + #if 0 + /* ??? This fails for nested inline functions, because context_display +--- gcc/function.c.orig 2005-11-17 23:01:55.000000000 -0200 ++++ gcc/function.c 2005-11-17 23:07:55.000000000 -0200 +@@ -2824,12 +2824,6 @@ + #endif + #endif + +-/* On most machines, the CFA coincides with the first incoming parm. */ +- +-#ifndef ARG_POINTER_CFA_OFFSET +-#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL) +-#endif +- + /* Build up a (MEM (ADDRESSOF (REG))) rtx for a register REG that just + had its address taken. DECL is the decl or SAVE_EXPR for the + object stored in the register, for later use if we do need to force +--- gcc/tree.h.orig 2005-11-17 23:06:26.000000000 -0200 ++++ gcc/tree.h 2005-11-17 23:07:55.000000000 -0200 +@@ -2065,7 +2065,6 @@ + + #define NULL_TREE (tree) NULL + +-extern GTY(()) tree frame_base_decl; + extern tree decl_assembler_name (tree); + + /* Compute the number of bytes occupied by 'node'. This routine only +--- gcc/var-tracking.c.orig 2005-11-17 23:01:55.000000000 -0200 ++++ gcc/var-tracking.c 2005-11-17 23:07:55.000000000 -0200 +@@ -266,19 +266,12 @@ + /* Shall notes be emitted? */ + static bool emit_notes; + +-/* Fake variable for stack pointer. */ +-tree frame_base_decl; +- +-/* Stack adjust caused by function prologue. */ +-static HOST_WIDE_INT frame_stack_adjust; +- + /* Local function prototypes. */ + static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, + HOST_WIDE_INT *); + static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, + HOST_WIDE_INT *); + static void bb_stack_adjust_offset (basic_block); +-static HOST_WIDE_INT prologue_stack_adjust (void); + static bool vt_stack_adjustments (void); + static rtx adjust_stack_reference (rtx, HOST_WIDE_INT); + static hashval_t variable_htab_hash (const void *); +@@ -333,7 +326,6 @@ + static void dump_dataflow_sets (void); + + static void variable_was_changed (variable, htab_t); +-static void set_frame_base_location (dataflow_set *, rtx); + static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); + static void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); + static int emit_note_insn_var_location (void **, void *); +@@ -489,38 +481,6 @@ + VTI (bb)->out.stack_adjust = offset; + } + +-/* Compute stack adjustment caused by function prologue. */ +- +-static HOST_WIDE_INT +-prologue_stack_adjust (void) +-{ +- HOST_WIDE_INT offset = 0; +- basic_block bb = ENTRY_BLOCK_PTR->next_bb; +- rtx insn; +- rtx end; +- +- if (!BB_END (bb)) +- return 0; +- +- end = NEXT_INSN (BB_END (bb)); +- for (insn = BB_HEAD (bb); insn != end; insn = NEXT_INSN (insn)) +- { +- if (GET_CODE (insn) == NOTE +- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END) +- break; +- +- if (INSN_P (insn)) +- { +- HOST_WIDE_INT tmp; +- +- insn_stack_adjust_offset_pre_post (insn, &tmp, &tmp); +- offset += tmp; +- } +- } +- +- return offset; +-} +- + /* Compute stack adjustments for all blocks by traversing DFS tree. + Return true when the adjustments on all incoming edges are consistent. + Heavily borrowed from flow_depth_first_order_compute. */ +@@ -533,7 +493,7 @@ + + /* Initialize entry block. */ + VTI (ENTRY_BLOCK_PTR)->visited = true; +- VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = frame_stack_adjust; ++ VTI (ENTRY_BLOCK_PTR)->out.stack_adjust = INCOMING_FRAME_SP_OFFSET; + + /* Allocate stack for back-tracking up CFG. */ + stack = xmalloc ((n_basic_blocks + 1) * sizeof (edge)); +@@ -587,27 +547,23 @@ + return true; + } + +-/* Adjust stack reference MEM by ADJUSTMENT bytes and return the new rtx. */ ++/* Adjust stack reference MEM by ADJUSTMENT bytes and make it relative ++ to the argument pointer. Return the new rtx. */ + + static rtx + adjust_stack_reference (rtx mem, HOST_WIDE_INT adjustment) + { +- rtx adjusted_mem; +- rtx tmp; ++ rtx addr, cfa, tmp; + +- if (adjustment == 0) +- return mem; ++ adjustment -= ARG_POINTER_CFA_OFFSET (current_function_decl); ++ cfa = plus_constant (arg_pointer_rtx, adjustment); + +- adjusted_mem = copy_rtx (mem); +- XEXP (adjusted_mem, 0) = replace_rtx (XEXP (adjusted_mem, 0), +- stack_pointer_rtx, +- gen_rtx_PLUS (Pmode, stack_pointer_rtx, +- GEN_INT (adjustment))); +- tmp = simplify_rtx (XEXP (adjusted_mem, 0)); ++ addr = replace_rtx (copy_rtx (XEXP (mem, 0)), stack_pointer_rtx, cfa); ++ tmp = simplify_rtx (addr); + if (tmp) +- XEXP (adjusted_mem, 0) = tmp; ++ addr = tmp; + +- return adjusted_mem; ++ return replace_equiv_address_nv (mem, addr); + } + + /* The hash function for variable_htab, computes the hash value +@@ -1657,14 +1613,7 @@ + break; + + case MO_ADJUST: +- { +- rtx base; +- +- out->stack_adjust += VTI (bb)->mos[i].u.adjust; +- base = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, +- out->stack_adjust)); +- set_frame_base_location (out, base); +- } ++ out->stack_adjust += VTI (bb)->mos[i].u.adjust; + break; + } + } +@@ -1786,8 +1735,7 @@ + for (; list; list = list->next) + { + print_mem_expr (rtl_dump_file, list->decl); +- fprintf (rtl_dump_file, "+"); +- fprintf (rtl_dump_file, HOST_WIDE_INT_PRINT_DEC, list->offset); ++ fprintf (rtl_dump_file, "+" HOST_WIDE_INT_PRINT_DEC, list->offset); + } + fprintf (rtl_dump_file, "\n"); + } +@@ -1837,9 +1785,8 @@ + { + int i; + +- fprintf (rtl_dump_file, "Stack adjustment: "); +- fprintf (rtl_dump_file, HOST_WIDE_INT_PRINT_DEC, set->stack_adjust); +- fprintf (rtl_dump_file, "\n"); ++ fprintf (rtl_dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n", ++ set->stack_adjust); + for (i = 1; i < FIRST_PSEUDO_REGISTER; i++) + { + if (set->regs[i]) +@@ -1921,37 +1868,6 @@ + } + } + +-/* Set the location of frame_base_decl to LOC in dataflow set SET. This +- function expects that frame_base_decl has already one location for offset 0 +- in the variable table. */ +- +-static void +-set_frame_base_location (dataflow_set *set, rtx loc) +-{ +- variable var; +- +- var = htab_find_with_hash (set->vars, frame_base_decl, +- VARIABLE_HASH_VAL (frame_base_decl)); +-#ifdef ENABLE_CHECKING +- if (!var) +- abort (); +- if (var->n_var_parts != 1) +- abort (); +- if (var->var_part[0].offset != 0) +- abort (); +- if (!var->var_part[0].loc_chain) +- abort (); +-#endif +- +- /* If frame_base_decl is shared unshare it first. */ +- if (var->refcount > 1) +- var = unshare_variable (set, var); +- +- var->var_part[0].loc_chain->loc = loc; +- var->var_part[0].cur_loc = loc; +- variable_was_changed (var, set->vars); +-} +- + /* Set the part of variable's location in the dataflow set SET. The variable + part is specified by variable's declaration DECL and offset OFFSET and the + part's location by LOC. */ +@@ -2482,15 +2398,7 @@ + break; + + case MO_ADJUST: +- { +- rtx base; +- +- set.stack_adjust += VTI (bb)->mos[i].u.adjust; +- base = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, +- set.stack_adjust)); +- set_frame_base_location (&set, base); +- emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); +- } ++ set.stack_adjust += VTI (bb)->mos[i].u.adjust; + break; + } + } +@@ -2600,7 +2508,6 @@ + abort (); + #endif + +- incoming = eliminate_regs (incoming, 0, NULL_RTX); + out = &VTI (ENTRY_BLOCK_PTR)->out; + + if (GET_CODE (incoming) == REG) +@@ -2614,9 +2521,7 @@ + set_variable_part (out, incoming, parm, offset); + } + else if (GET_CODE (incoming) == MEM) +- { +- set_variable_part (out, incoming, parm, offset); +- } ++ set_variable_part (out, incoming, parm, offset); + } + } + +@@ -2761,28 +2666,6 @@ + changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq, + NULL); + vt_add_function_parameters (); +- +- if (!frame_pointer_needed) +- { +- rtx base; +- +- /* Create fake variable for tracking stack pointer changes. */ +- frame_base_decl = make_node (VAR_DECL); +- DECL_NAME (frame_base_decl) = get_identifier ("___frame_base_decl"); +- TREE_TYPE (frame_base_decl) = char_type_node; +- DECL_ARTIFICIAL (frame_base_decl) = 1; +- DECL_IGNORED_P (frame_base_decl) = 1; +- +- /* Set its initial "location". */ +- frame_stack_adjust = -prologue_stack_adjust (); +- base = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, +- frame_stack_adjust)); +- set_variable_part (&VTI (ENTRY_BLOCK_PTR)->out, base, frame_base_decl, 0); +- } +- else +- { +- frame_base_decl = NULL; +- } + } + + /* Free the data structures needed for variable tracking. */ diff --git a/SOURCES/gcc34-dwarf2-i386-multreg1.patch b/SOURCES/gcc34-dwarf2-i386-multreg1.patch new file mode 100644 index 0000000..bbd3228 --- /dev/null +++ b/SOURCES/gcc34-dwarf2-i386-multreg1.patch @@ -0,0 +1,27 @@ +2005-11-09 Jakub Jelinek + + * dwarf2out.c (multiple_reg_loc_descriptor): Don't assume + DBX_REGISTER_NUMBER being contiguous. + +--- gcc/dwarf2out.c (revision 106711) ++++ gcc/dwarf2out.c (revision 106712) +@@ -8411,7 +8411,9 @@ + unsigned reg; + dw_loc_descr_ref loc_result = NULL; + +- reg = dbx_reg_number (rtl); ++ reg = REGNO (rtl); ++ if ((unsigned) DBX_REGISTER_NUMBER (reg) != dbx_reg_number (rtl)) ++ abort (); + nregs = HARD_REGNO_NREGS (REGNO (rtl), GET_MODE (rtl)); + + /* Simple, contiguous registers. */ +@@ -8424,7 +8426,7 @@ + { + dw_loc_descr_ref t; + +- t = one_reg_loc_descriptor (reg); ++ t = one_reg_loc_descriptor (DBX_REGISTER_NUMBER (reg)); + add_loc_descr (&loc_result, t); + add_loc_descr_op_piece (&loc_result, size); + ++reg; diff --git a/SOURCES/gcc34-dwarf2-i386-multreg2.patch b/SOURCES/gcc34-dwarf2-i386-multreg2.patch new file mode 100644 index 0000000..7ab3052 --- /dev/null +++ b/SOURCES/gcc34-dwarf2-i386-multreg2.patch @@ -0,0 +1,17 @@ +2005-11-30 Jakub Jelinek + + * dwarf2out.c (multiple_reg_loc_descriptor): Remap reg with + LEAF_REG_REMAP. + +--- gcc/dwarf2out.c.jj 2005-11-21 10:57:57.000000000 +0100 ++++ gcc/dwarf2out.c 2005-11-30 21:35:28.000000000 +0100 +@@ -8271,6 +8271,9 @@ multiple_reg_loc_descriptor (rtx rtl, rt + dw_loc_descr_ref loc_result = NULL; + + reg = REGNO (rtl); ++#ifdef LEAF_REG_REMAP ++ reg = LEAF_REG_REMAP (reg); ++#endif + if ((unsigned) DBX_REGISTER_NUMBER (reg) != dbx_reg_number (rtl)) + abort (); + nregs = HARD_REGNO_NREGS (REGNO (rtl), GET_MODE (rtl)); diff --git a/SOURCES/gcc34-dwarf2-inline-details-fix.patch b/SOURCES/gcc34-dwarf2-inline-details-fix.patch new file mode 100644 index 0000000..5cfe6d7 --- /dev/null +++ b/SOURCES/gcc34-dwarf2-inline-details-fix.patch @@ -0,0 +1,26 @@ +2006-11-07 Alexandre Oliva + + * tree-inline.c (expand_call_inline): Set BLOCK_SOURCE_LOCATION. + +--- gcc/tree-inline.c.orig 2006-10-13 04:31:24.000000000 -0300 ++++ gcc/tree-inline.c 2006-11-07 04:06:10.000000000 -0200 +@@ -1253,6 +1253,7 @@ expand_call_inline (tree *tp, int *walk_ + tree args; + tree return_slot_addr; + const char *reason; ++ location_t incoming_loc = input_location; + + /* See what we've got. */ + id = (inline_data *) data; +@@ -1464,7 +1465,10 @@ expand_call_inline (tree *tp, int *walk_ + /* Tell the debugging backends that this block represents the + outermost scope of the inlined function. */ + if (SCOPE_STMT_BLOCK (scope_stmt)) +- BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope_stmt)) = DECL_ORIGIN (fn); ++ { ++ BLOCK_ABSTRACT_ORIGIN (SCOPE_STMT_BLOCK (scope_stmt)) = DECL_ORIGIN (fn); ++ BLOCK_SOURCE_LOCATION (SCOPE_STMT_BLOCK (scope_stmt)) = incoming_loc; ++ } + + /* Declare the return variable for the function. */ + COMPOUND_BODY (stmt) diff --git a/SOURCES/gcc34-dwarf2-inline-details.patch b/SOURCES/gcc34-dwarf2-inline-details.patch new file mode 100644 index 0000000..ecd6b5b --- /dev/null +++ b/SOURCES/gcc34-dwarf2-inline-details.patch @@ -0,0 +1,115 @@ +2005-07-25 James E Wilson + + * dwarf2out.c (add_call_src_coords_attributes): New. + (gen_inlined_subroutine_die): Call it. + (maybe_emit_file, init_file_table): Add comments. + (prune_unused_types_walk_attribs): Pass DW_AT_call_file through + maybe_emit_file. + * tree-inline.c (remap_block): Copy BLOCK_SOURCE_LOCATION. + (expand_call_inline): Set BLOCK_SOURCE_LOCATION. + * tree.h (BLOCK_SOURCE_LOCATION): New. + (struct tree_block): New field locus. + +--- gcc/dwarf2out.c.orig 2005-11-17 23:37:43.000000000 -0200 ++++ gcc/dwarf2out.c 2005-11-17 23:38:25.000000000 -0200 +@@ -11509,6 +11509,20 @@ + } + } + ++/* A helper function for gen_inlined_subroutine_die. Add source coordinate ++ attributes to the DIE for a block STMT, to describe where the inlined ++ function was called from. This is similar to add_src_coords_attributes. */ ++ ++static inline void ++add_call_src_coords_attributes (tree stmt, dw_die_ref die) ++{ ++ unsigned file_index = BLOCK_SOURCE_LOCATION (stmt).file ++ ? lookup_filename (BLOCK_SOURCE_LOCATION (stmt).file) : 0; ++ ++ add_AT_unsigned (die, DW_AT_call_file, file_index); ++ add_AT_unsigned (die, DW_AT_call_line, BLOCK_SOURCE_LOCATION (stmt).line); ++} ++ + /* A helper function for gen_lexical_block_die and gen_inlined_subroutine_die. + Add low_pc and high_pc attributes to the DIE for a block STMT. */ + +@@ -11576,6 +11590,7 @@ + + add_abstract_origin_attribute (subr_die, decl); + add_high_low_attributes (stmt, subr_die); ++ add_call_src_coords_attributes (stmt, subr_die); + + decls_for_scope (stmt, subr_die, depth); + current_function_has_inlines = 1; +@@ -12824,6 +12839,12 @@ + return i; + } + ++/* If the assembler will construct the file table, then translate the compiler ++ internal file table number into the assembler file table number, and emit ++ a .file directive if we haven't already emitted one yet. The file table ++ numbers are different because we prune debug info for unused variables and ++ types, which may include filenames. */ ++ + static int + maybe_emit_file (int fileno) + { +@@ -12844,6 +12865,8 @@ + return fileno; + } + ++/* Initialize the compiler internal file table. */ ++ + static void + init_file_table (void) + { +@@ -13207,7 +13230,7 @@ + Make sure that it will get emitted. */ + prune_unused_types_mark (a->dw_attr_val.v.val_die_ref.die, 1); + } +- else if (a->dw_attr == DW_AT_decl_file) ++ else if (a->dw_attr == DW_AT_decl_file || a->dw_attr == DW_AT_call_file) + { + /* A reference to a file. Make sure the file name is emitted. */ + a->dw_attr_val.v.val_unsigned = +--- gcc/tree-inline.c.orig 2005-11-17 23:37:02.000000000 -0200 ++++ gcc/tree-inline.c 2005-11-17 23:37:46.000000000 -0200 +@@ -346,6 +346,7 @@ + new_block = make_node (BLOCK); + TREE_USED (new_block) = TREE_USED (old_block); + BLOCK_ABSTRACT_ORIGIN (new_block) = old_block; ++ BLOCK_SOURCE_LOCATION (new_block) = BLOCK_SOURCE_LOCATION (old_block); + SCOPE_STMT_BLOCK (scope_stmt) = new_block; + + /* Remap its variables. */ +@@ -420,6 +421,7 @@ + new_block = make_node (BLOCK); + TREE_USED (new_block) = TREE_USED (old_block); + BLOCK_ABSTRACT_ORIGIN (new_block) = old_block; ++ BLOCK_SOURCE_LOCATION (new_block) = BLOCK_SOURCE_LOCATION (old_block); + BLOCK_SUBBLOCKS (new_block) = BLOCK_SUBBLOCKS (old_block); + TREE_SIDE_EFFECTS (new_block) = TREE_SIDE_EFFECTS (old_block); + TREE_TYPE (new_block) = TREE_TYPE (old_block); +--- gcc/tree.h.orig 2005-11-17 23:37:02.000000000 -0200 ++++ gcc/tree.h 2005-11-17 23:37:46.000000000 -0200 +@@ -903,6 +903,12 @@ + #define BLOCK_FRAGMENT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.fragment_origin) + #define BLOCK_FRAGMENT_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.fragment_chain) + ++/* For an inlined function, this gives the location where it was called ++ from. This is only set in the top level block, which corresponds to the ++ inlined function scope. This is used in the debug output routines. */ ++ ++#define BLOCK_SOURCE_LOCATION(NODE) (BLOCK_CHECK (NODE)->block.locus) ++ + struct tree_block GTY(()) + { + struct tree_common common; +@@ -917,6 +923,7 @@ + tree abstract_origin; + tree fragment_origin; + tree fragment_chain; ++ location_t locus; + }; + + /* Define fields and accessors for nodes representing data types. */ diff --git a/SOURCES/gcc34-dwarf2-pr20268.patch b/SOURCES/gcc34-dwarf2-pr20268.patch new file mode 100644 index 0000000..e6b4c51 --- /dev/null +++ b/SOURCES/gcc34-dwarf2-pr20268.patch @@ -0,0 +1,102 @@ +2005-03-30 James E. Wilson + + PR debug/20268 + * dwarf2out.c (add_high_low_attributes): New function, extracted from + gen_lexical_block_die. + (gen_lexical_block_die, gen_inlined_subroutine_die): Call it. + +--- gcc/dwarf2out.c.orig 2005-11-17 18:30:11.000000000 -0200 ++++ gcc/dwarf2out.c 2005-11-17 18:31:51.000000000 -0200 +@@ -11509,41 +11509,49 @@ + } + } + +-/* Generate a DIE for a lexical block. */ ++/* A helper function for gen_lexical_block_die and gen_inlined_subroutine_die. ++ Add low_pc and high_pc attributes to the DIE for a block STMT. */ + +-static void +-gen_lexical_block_die (tree stmt, dw_die_ref context_die, int depth) ++static inline void ++add_high_low_attributes (tree stmt, dw_die_ref die) + { +- dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt); + char label[MAX_ARTIFICIAL_LABEL_BYTES]; + +- if (! BLOCK_ABSTRACT (stmt)) ++ if (BLOCK_FRAGMENT_CHAIN (stmt)) + { +- if (BLOCK_FRAGMENT_CHAIN (stmt)) +- { +- tree chain; ++ tree chain; + +- add_AT_range_list (stmt_die, DW_AT_ranges, add_ranges (stmt)); ++ add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt)); + +- chain = BLOCK_FRAGMENT_CHAIN (stmt); +- do +- { +- add_ranges (chain); +- chain = BLOCK_FRAGMENT_CHAIN (chain); +- } +- while (chain); +- add_ranges (NULL); +- } +- else ++ chain = BLOCK_FRAGMENT_CHAIN (stmt); ++ do + { +- ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, +- BLOCK_NUMBER (stmt)); +- add_AT_lbl_id (stmt_die, DW_AT_low_pc, label); +- ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, +- BLOCK_NUMBER (stmt)); +- add_AT_lbl_id (stmt_die, DW_AT_high_pc, label); ++ add_ranges (chain); ++ chain = BLOCK_FRAGMENT_CHAIN (chain); + } ++ while (chain); ++ add_ranges (NULL); ++ } ++ else ++ { ++ ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, ++ BLOCK_NUMBER (stmt)); ++ add_AT_lbl_id (die, DW_AT_low_pc, label); ++ ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, ++ BLOCK_NUMBER (stmt)); ++ add_AT_lbl_id (die, DW_AT_high_pc, label); + } ++} ++ ++/* Generate a DIE for a lexical block. */ ++ ++static void ++gen_lexical_block_die (tree stmt, dw_die_ref context_die, int depth) ++{ ++ dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt); ++ ++ if (! BLOCK_ABSTRACT (stmt)) ++ add_high_low_attributes (stmt, stmt_die); + + decls_for_scope (stmt, stmt_die, depth); + } +@@ -11565,15 +11573,10 @@ + { + dw_die_ref subr_die + = new_die (DW_TAG_inlined_subroutine, context_die, stmt); +- char label[MAX_ARTIFICIAL_LABEL_BYTES]; + + add_abstract_origin_attribute (subr_die, decl); +- ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_BEGIN_LABEL, +- BLOCK_NUMBER (stmt)); +- add_AT_lbl_id (subr_die, DW_AT_low_pc, label); +- ASM_GENERATE_INTERNAL_LABEL (label, BLOCK_END_LABEL, +- BLOCK_NUMBER (stmt)); +- add_AT_lbl_id (subr_die, DW_AT_high_pc, label); ++ add_high_low_attributes (stmt, subr_die); ++ + decls_for_scope (stmt, subr_die, depth); + current_function_has_inlines = 1; + } diff --git a/SOURCES/gcc34-dwarf2-prefer-1elt-vartracking.patch b/SOURCES/gcc34-dwarf2-prefer-1elt-vartracking.patch new file mode 100644 index 0000000..4c5c05a --- /dev/null +++ b/SOURCES/gcc34-dwarf2-prefer-1elt-vartracking.patch @@ -0,0 +1,25 @@ +2005-08-10 Jakub Jelinek + + * dwarf2out.c (add_location_or_const_value_attribute): Prefer + locations gathered by var-tracking in single entry loc_list + over loc_descriptor_from_tree. + +--- gcc/dwarf2out.c.orig 2005-11-17 23:03:34.000000000 -0200 ++++ gcc/dwarf2out.c 2005-11-17 23:05:54.000000000 -0200 +@@ -9921,7 +9921,15 @@ + + rtl = rtl_for_decl_location (decl); + if (rtl == NULL_RTX) +- return; ++ { ++ /* We couldn't get any rtl, so try directly generating the ++ location description from the tree. */ ++ descr = loc_descriptor_from_tree (decl, 0); ++ if (descr) ++ add_AT_location_description (die, attr, descr); ++ ++ return; ++ } + + switch (GET_CODE (rtl)) + { diff --git a/SOURCES/gcc34-dwarf2-usefbreg.patch b/SOURCES/gcc34-dwarf2-usefbreg.patch new file mode 100644 index 0000000..1a1dfb5 --- /dev/null +++ b/SOURCES/gcc34-dwarf2-usefbreg.patch @@ -0,0 +1,112 @@ +2005-08-10 Jakub Jelinek + + * dwarf2out.c (concat_loc_descriptor): Add can_use_fbreg argument, + pass it down to loc_descriptor. + (loc_descriptor): Pass can_use_fbreg to concat_loc_descriptor. + (containing_function_has_frame_base): Move earlier in the file. + (loc_descriptor_from_tree_1): Use containing_function_has_frame_base + instead of always assuming fbreg can't be used. + +--- gcc/dwarf2out.c.orig 2005-09-22 17:13:19.000000000 -0300 ++++ gcc/dwarf2out.c 2005-11-15 20:26:07.000000000 -0200 +@@ -3755,7 +3755,7 @@ + static dw_loc_descr_ref based_loc_descr (unsigned, HOST_WIDE_INT, bool); + static int is_based_loc (rtx); + static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode, bool); +-static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx); ++static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx, bool); + static dw_loc_descr_ref loc_descriptor (rtx, bool); + static dw_loc_descr_ref loc_descriptor_from_tree (tree, int); + static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int); +@@ -8562,11 +8562,11 @@ + This is typically a complex variable. */ + + static dw_loc_descr_ref +-concat_loc_descriptor (rtx x0, rtx x1) ++concat_loc_descriptor (rtx x0, rtx x1, bool can_use_fbreg) + { + dw_loc_descr_ref cc_loc_result = NULL; +- dw_loc_descr_ref x0_ref = loc_descriptor (x0, true); +- dw_loc_descr_ref x1_ref = loc_descriptor (x1, true); ++ dw_loc_descr_ref x0_ref = loc_descriptor (x0, can_use_fbreg); ++ dw_loc_descr_ref x1_ref = loc_descriptor (x1, can_use_fbreg); + + if (x0_ref == 0 || x1_ref == 0) + return 0; +@@ -8580,6 +8580,29 @@ + return cc_loc_result; + } + ++/* Return true if DECL's containing function has a frame base attribute. ++ Return false otherwise. */ ++ ++static bool ++containing_function_has_frame_base (tree decl) ++{ ++ tree declcontext = decl_function_context (decl); ++ dw_die_ref context; ++ dw_attr_ref attr; ++ ++ if (!declcontext) ++ return false; ++ ++ context = lookup_decl_die (declcontext); ++ if (!context) ++ return false; ++ ++ for (attr = context->die_attr; attr; attr = attr->dw_attr_next) ++ if (attr->dw_attr == DW_AT_frame_base) ++ return true; ++ return false; ++} ++ + /* Output a proper Dwarf location descriptor for a variable or parameter + which is either allocated in a register or in a memory location. For a + register, we just generate an OP_REG and the register number. For a +@@ -8615,7 +8638,8 @@ + break; + + case CONCAT: +- loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1)); ++ loc_result = concat_loc_descriptor (XEXP (rtl, 0), XEXP (rtl, 1), ++ can_use_fbreg); + break; + + case VAR_LOCATION: +@@ -8765,6 +8789,7 @@ + else + { + enum machine_mode mode = GET_MODE (rtl); ++ bool can_use_fb = containing_function_has_frame_base (loc); + + if (GET_CODE (rtl) == MEM) + { +@@ -8772,7 +8797,7 @@ + rtl = XEXP (rtl, 0); + } + +- ret = mem_loc_descriptor (rtl, mode, true); ++ ret = mem_loc_descriptor (rtl, mode, can_use_fb); + } + } + break; +@@ -8847,16 +8872,18 @@ + /* Get an RTL for this, if something has been emitted. */ + rtx rtl = lookup_constant_def (loc); + enum machine_mode mode; ++ bool can_use_fb; + + if (GET_CODE (rtl) != MEM) + return 0; ++ can_use_fb = containing_function_has_frame_base (loc); + mode = GET_MODE (rtl); + rtl = XEXP (rtl, 0); + + rtl = (*targetm.delegitimize_address) (rtl); + + indirect_p = 1; +- ret = mem_loc_descriptor (rtl, mode, true); ++ ret = mem_loc_descriptor (rtl, mode, can_use_fb); + break; + } + diff --git a/SOURCES/gcc34-frame-base-loclist.patch b/SOURCES/gcc34-frame-base-loclist.patch new file mode 100644 index 0000000..fdc64bd --- /dev/null +++ b/SOURCES/gcc34-frame-base-loclist.patch @@ -0,0 +1,143 @@ +2006-05-19 Jakub Jelinek + + * dwarf2out.c (gen_subprogram_die): If -fno-frame-base-loclist, + set frame base to hard fp or stack pointer. + * toplev.c (flag_frame_base_loclist): New variable. + (f_options): Add -fframe-base-loclist. + * flags.h (flag_frame_base_loclist): New extern. + * common.opt (frame-base-loclist): New flag. + * opts.c (common_handle_option): Handle -f{,no-}frame-base-loclist. + +--- gcc/dwarf2out.c.jj 2006-05-15 14:02:35.000000000 +0200 ++++ gcc/dwarf2out.c 2006-05-15 14:21:40.000000000 +0200 +@@ -11389,33 +11389,35 @@ gen_subprogram_die (tree decl, dw_die_re + #endif + + #ifdef DWARF2_UNWIND_INFO +- /* We define the "frame base" as the function's CFA. This is more +- convenient for several reasons: (1) It's stable across the prologue +- and epilogue, which makes it better than just a frame pointer, +- (2) With dwarf3, there exists a one-byte encoding that allows us +- to reference the .debug_frame data by proxy, but failing that, +- (3) We can at least reuse the code inspection and interpretation +- code that determines the CFA position at various points in the +- function. */ +- /* ??? Use some command-line or configury switch to enable the use +- of dwarf3 DW_OP_call_frame_cfa. At present there are no dwarf +- consumers that understand it; fall back to "pure" dwarf2 and +- convert the CFA data into a location list. */ +- { +- dw_loc_list_ref list = convert_cfa_to_loc_list (); +- if (list->dw_loc_next) +- add_AT_loc_list (subr_die, DW_AT_frame_base, list); +- else +- add_AT_loc (subr_die, DW_AT_frame_base, list->expr); +- } ++ if (flag_frame_base_loclist) ++ { ++ /* We define the "frame base" as the function's CFA. This is more ++ convenient for several reasons: (1) It's stable across the prologue ++ and epilogue, which makes it better than just a frame pointer, ++ (2) With dwarf3, there exists a one-byte encoding that allows us ++ to reference the .debug_frame data by proxy, but failing that, ++ (3) We can at least reuse the code inspection and interpretation ++ code that determines the CFA position at various points in the ++ function. */ ++ /* ??? Use some command-line or configury switch to enable the use ++ of dwarf3 DW_OP_call_frame_cfa. At present there are no dwarf ++ consumers that understand it; fall back to "pure" dwarf2 and ++ convert the CFA data into a location list. */ ++ dw_loc_list_ref list = convert_cfa_to_loc_list (); ++ if (list->dw_loc_next) ++ add_AT_loc_list (subr_die, DW_AT_frame_base, list); ++ else ++ add_AT_loc (subr_die, DW_AT_frame_base, list->expr); + +- /* Compute a displacement from the "steady-state frame pointer" to +- the CFA. The former is what all stack slots and argument slots +- will reference in the rtl; the later is what we've told the +- debugger about. We'll need to adjust all frame_base references +- by this displacement. */ +- compute_frame_pointer_to_cfa_displacement (); +-#else ++ /* Compute a displacement from the "steady-state frame pointer" to ++ the CFA. The former is what all stack slots and argument slots ++ will reference in the rtl; the later is what we've told the ++ debugger about. We'll need to adjust all frame_base references ++ by this displacement. */ ++ compute_frame_pointer_to_cfa_displacement (); ++ } ++ else ++#endif + /* For targets which support DWARF2, but not DWARF2 call-frame info, + we just use the stack pointer or frame pointer. */ + /* ??? Should investigate getting better info via callbacks, or else +@@ -11425,7 +11427,6 @@ gen_subprogram_die (tree decl, dw_die_re + = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; + add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); + } +-#endif + + #if 0 + /* ??? This fails for nested inline functions, because context_display +--- gcc/toplev.c.jj 2005-11-21 14:55:43.000000000 +0100 ++++ gcc/toplev.c 2006-05-15 14:25:14.000000000 +0200 +@@ -961,6 +961,10 @@ int flag_tracer = 0; + + int flag_unit_at_a_time = 0; + ++/* Nonzero if DWARF2 DW_AT_frame_base can be a location list. */ ++ ++int flag_frame_base_loclist = 1; ++ + /* Nonzero if we should track variables. When + flag_var_tracking == AUTODETECT_FLAG_VAR_TRACKING it will be set according + to optimize, debug_info_level and debug_hooks in process_options (). */ +@@ -1165,7 +1169,8 @@ static const lang_independent_options f_ + { "trapv", &flag_trapv, 1 }, + { "wrapv", &flag_wrapv, 1 }, + { "new-ra", &flag_new_regalloc, 1 }, +- { "var-tracking", &flag_var_tracking, 1} ++ { "var-tracking", &flag_var_tracking, 1}, ++ { "frame-base-loclist", &flag_frame_base_loclist, 1} + }; + + /* Here is a table, controlled by the tm.h file, listing each -m switch +--- gcc/flags.h.jj 2005-11-21 14:43:20.000000000 +0100 ++++ gcc/flags.h 2006-05-15 14:25:06.000000000 +0200 +@@ -746,6 +746,9 @@ extern int flag_remove_unreachable_funct + /* Nonzero if we should track variables. */ + extern int flag_var_tracking; + ++/* Nonzero if DWARF2 DW_AT_frame_base can be a location list. */ ++extern int flag_frame_base_loclist; ++ + /* A string that's used when a random name is required. NULL means + to make it really random. */ + +--- gcc/common.opt.jj 2005-11-21 08:43:20.000000000 -0500 ++++ gcc/common.opt 2006-05-19 06:24:09.000000000 -0400 +@@ -718,6 +718,10 @@ fvar-tracking + Common + Perform variable tracking + ++fframe-base-loclist ++Common ++Allow use of DWARF2 location lists for frame base ++ + fverbose-asm + Common + Add extra commentary to assembler output +--- gcc/opts.c.jj 2005-11-21 08:43:21.000000000 -0500 ++++ gcc/opts.c 2006-05-19 06:26:26.000000000 -0400 +@@ -1461,6 +1461,10 @@ common_handle_option (size_t scode, cons + flag_var_tracking = value; + break; + ++ case OPT_fframe_base_loclist: ++ flag_frame_base_loclist = value; ++ break; ++ + case OPT_fverbose_asm: + flag_verbose_asm = value; + break; diff --git a/SOURCES/gcc34-gnuc-rh-release.patch b/SOURCES/gcc34-gnuc-rh-release.patch new file mode 100644 index 0000000..9a9debc --- /dev/null +++ b/SOURCES/gcc34-gnuc-rh-release.patch @@ -0,0 +1,54 @@ +2004-10-18 Jakub Jelinek + + * c-cppbuiltin.c (define__GNUC__): Also define __GNUC_RH_RELEASE__. + +--- gcc/c-cppbuiltin.c.jj 2004-03-08 18:48:58.000000000 +0100 ++++ gcc/c-cppbuiltin.c 2004-10-18 16:40:14.450009521 +0200 +@@ -254,14 +254,14 @@ define__GNUC__ (void) + { + /* The format of the version string, enforced below, is + ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */ +- const char *q, *v = version_string; ++ const char *q, *v = version_string, *vstart, *vend; + + while (*v && ! ISDIGIT (*v)) + v++; + if (!*v || (v > version_string && v[-1] != '-')) + abort (); + +- q = v; ++ vstart = q = v; + while (ISDIGIT (*v)) + v++; + builtin_define_with_value_n ("__GNUC__", q, v - q); +@@ -289,6 +289,30 @@ define__GNUC__ (void) + + if (*v && *v != ' ' && *v != '-') + abort (); ++ ++ vend = v; ++ v = strchr (v, '('); ++ if (v != NULL && strncmp (v + 1, "Red Hat ", 8) == 0) ++ { ++ v += 9; ++ if (strncmp (v, "Linux ", 6) == 0) ++ v += 6; ++ ++ if (strncmp (v, vstart, vend - vstart) != 0 ++ || v[vend - vstart] != '-') ++ abort (); ++ ++ v += vend - vstart + 1; ++ q = v; ++ if (!ISDIGIT (*v)) ++ abort (); ++ while (ISDIGIT (*v)) ++ v++; ++ builtin_define_with_value_n ("__GNUC_RH_RELEASE__", q, v - q); ++ ++ if (*v && *v != ')' && *v != '.') ++ abort (); ++ } + } + + /* Hook that registers front end and target-specific built-ins. */ diff --git a/SOURCES/gcc34-hashtab-recursion.patch b/SOURCES/gcc34-hashtab-recursion.patch new file mode 100644 index 0000000..3b4ada3 --- /dev/null +++ b/SOURCES/gcc34-hashtab-recursion.patch @@ -0,0 +1,74 @@ +2005-05-17 Jakub Jelinek + + * varasm.c (struct constant_descriptor_tree): Add hash field. + (const_desc_hash): Just return hash field. + (const_desc_eq): If hash values are different, return 0 immediately. + (output_constant_def): Compute hash field of temporary key, use + htab_find_slot_with_hash instead of htab_find_slot. Set hash in + newly built constant descriptor. + (lookup_constant_def): Compute hash field of temporary key, use + htab_find_with_hash instead of htab_find. + +--- gcc/varasm.c 16 May 2005 21:37:01 -0000 1.510 ++++ gcc/varasm.c 17 May 2005 06:34:48 -0000 1.511 +@@ -2361,6 +2361,11 @@ struct constant_descriptor_tree GTY(()) + + /* The value of the constant. */ + tree value; ++ ++ /* Hash of value. Computing the hash from value each time ++ hashfn is called can't work properly, as that means recursive ++ use of the hash table during hash table expansion. */ ++ hashval_t hash; + }; + + static GTY((param_is (struct constant_descriptor_tree))) +@@ -2374,7 +2379,7 @@ static void maybe_output_constant_def_co + static hashval_t + const_desc_hash (const void *ptr) + { +- return const_hash_1 (((struct constant_descriptor_tree *)ptr)->value); ++ return ((struct constant_descriptor_tree *)ptr)->hash; + } + + static hashval_t +@@ -2474,8 +2479,11 @@ const_hash_1 (const tree exp) + static int + const_desc_eq (const void *p1, const void *p2) + { +- return compare_constant (((struct constant_descriptor_tree *)p1)->value, +- ((struct constant_descriptor_tree *)p2)->value); ++ const struct constant_descriptor_tree *c1 = p1; ++ const struct constant_descriptor_tree *c2 = p2; ++ if (c1->hash != c2->hash) ++ return 0; ++ return compare_constant (c1->value, c2->value); + } + + /* Compare t1 and t2, and return 1 only if they are known to result in +@@ -2745,12 +2753,14 @@ output_constant_def (tree exp, int defer + /* Look up EXP in the table of constant descriptors. If we didn't find + it, create a new one. */ + key.value = exp; +- loc = htab_find_slot (const_desc_htab, &key, INSERT); ++ key.hash = const_hash_1 (exp); ++ loc = htab_find_slot_with_hash (const_desc_htab, &key, key.hash, INSERT); + + desc = *loc; + if (desc == 0) + { + desc = build_constant_desc (exp); ++ desc->hash = key.hash; + *loc = desc; + } + +@@ -2853,7 +2863,8 @@ lookup_constant_def (tree exp) + struct constant_descriptor_tree key; + + key.value = exp; +- desc = htab_find (const_desc_htab, &key); ++ key.hash = const_hash_1 (exp); ++ desc = htab_find_with_hash (const_desc_htab, &key, key.hash); + + return (desc ? desc->rtl : NULL_RTX); + } diff --git a/SOURCES/gcc34-i386-movsi-insv.patch b/SOURCES/gcc34-i386-movsi-insv.patch new file mode 100644 index 0000000..f21874a --- /dev/null +++ b/SOURCES/gcc34-i386-movsi-insv.patch @@ -0,0 +1,64 @@ +2005-05-10 Jakub Jelinek + + * config/i386/i386.md (movsi_insv_1, movdi_insv_1_rex64): Mask + CONST_INT values with 255. + + * gcc.dg/20050510-2.c: New test. + +--- gcc/config/i386/i386.md.jj 2005-05-10 00:47:12.000000000 +0200 ++++ gcc/config/i386/i386.md 2005-05-10 14:01:42.000000000 +0200 +@@ -1771,7 +1771,11 @@ + (const_int 8)) + (match_operand:SI 1 "general_operand" "Qmn"))] + "!TARGET_64BIT" +- "mov{b}\t{%b1, %h0|%h0, %b1}" ++{ ++ if (GET_CODE (operands[1]) == CONST_INT) ++ operands[1] = GEN_INT (INTVAL (operands[1]) & 255); ++ return "mov{b}\t{%b1, %h0|%h0, %b1}"; ++} + [(set_attr "type" "imov") + (set_attr "mode" "QI")]) + +@@ -1781,7 +1785,11 @@ + (const_int 8)) + (match_operand:DI 1 "nonmemory_operand" "Qn"))] + "TARGET_64BIT" +- "mov{b}\t{%b1, %h0|%h0, %b1}" ++{ ++ if (GET_CODE (operands[1]) == CONST_INT) ++ operands[1] = GEN_INT (INTVAL (operands[1]) & 255); ++ return "mov{b}\t{%b1, %h0|%h0, %b1}"; ++} + [(set_attr "type" "imov") + (set_attr "mode" "QI")]) + +--- gcc/testsuite/gcc.dg/20050510-2.c.jj 2005-04-07 15:51:53.775361896 +0200 ++++ gcc/testsuite/gcc.dg/20050510-2.c 2005-05-10 14:37:12.000000000 +0200 +@@ -0,0 +1,26 @@ ++/* { dg-options run } */ ++/* { dg-options "-O2" } */ ++ ++extern void abort (void); ++ ++__attribute__((noinline)) int ++foo (unsigned char *x) ++{ ++ if (x[0] != 1 || x[1] != 0x15) ++ abort (); ++ return 0; ++} ++ ++static inline void ++bar (unsigned short x) ++{ ++ unsigned char s[2] = { x >> 8, x & 0xff }; ++ foo (s); ++} ++ ++int ++main (void) ++{ ++ bar (0x115); ++ return 0; ++} diff --git a/SOURCES/gcc34-ia64-lib64.patch b/SOURCES/gcc34-ia64-lib64.patch new file mode 100644 index 0000000..8e6860b --- /dev/null +++ b/SOURCES/gcc34-ia64-lib64.patch @@ -0,0 +1,38 @@ +2004-05-14 Jakub Jelinek + + * gcc/config/ia64/ia64.h (TARGET_SWITCHES): Add -m64. + * gcc/config/ia64/t-glibc (MULTILIB_OPTIONS, MULTILIB_DIRNAMES, + MULTILIB_EXCEPTIONS, MULTILIB_OSDIRNAMES): Set. + * gcc/config/ia64/linux.h (MULTILIB_DEFAULTS): Define. + +--- gcc/config/ia64/ia64.h.jj 2004-03-12 08:14:28.000000000 -0500 ++++ gcc/config/ia64/ia64.h 2004-05-14 07:56:35.000000000 -0400 +@@ -168,6 +168,8 @@ extern int ia64_tls_size; + + #define TARGET_SWITCHES \ + { \ ++ { "64", 0, \ ++ N_("Generate 64-bit code") }, \ + { "big-endian", MASK_BIG_ENDIAN, \ + N_("Generate big endian code") }, \ + { "little-endian", -MASK_BIG_ENDIAN, \ +--- gcc/config/ia64/t-glibc.jj 2003-03-26 10:56:04.000000000 -0500 ++++ gcc/config/ia64/t-glibc 2004-05-14 08:30:15.000000000 -0400 +@@ -1 +1,6 @@ + LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c ++ ++MULTILIB_OPTIONS = m64/m32 ++MULTILIB_DIRNAMES = 64 32 ++MULTILIB_EXCEPTIONS = m32 ++MULTILIB_OSDIRNAMES = ../lib64 ../lib +--- gcc/config/ia64/linux.h.jj 2004-02-10 07:20:51.000000000 -0500 ++++ gcc/config/ia64/linux.h 2004-05-14 07:21:27.000000000 -0400 +@@ -55,6 +55,8 @@ do { \ + #undef LINK_EH_SPEC + #define LINK_EH_SPEC "" + ++#define MULTILIB_DEFAULTS { "m64" } ++ + /* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + diff --git a/SOURCES/gcc34-ice-hack.patch b/SOURCES/gcc34-ice-hack.patch new file mode 100644 index 0000000..dd1669f --- /dev/null +++ b/SOURCES/gcc34-ice-hack.patch @@ -0,0 +1,327 @@ +2004-01-23 Jakub Jelinek + + * system.h (ICE_EXIT_CODE): Define. + * gcc.c (execute): Don't free first string early, but at the end + of the function. Call retry_ice if compiler exited with + ICE_EXIT_CODE. + (retry_ice): New function. + * diagnostic.c (diagnostic_count_diagnostic, + diagnostic_action_after_output, error_recursion): Exit with + ICE_EXIT_CODE instead of FATAL_EXIT_CODE. + +--- gcc/system.h.jj 2004-01-19 17:29:30.000000000 +0100 ++++ gcc/system.h 2004-01-21 11:53:41.000000000 +0100 +@@ -153,6 +153,10 @@ extern int errno; + # endif + #endif + ++#ifndef ICE_EXIT_CODE ++# define ICE_EXIT_CODE 27 ++#endif ++ + #ifdef HAVE_UNISTD_H + # include + #endif +--- gcc/gcc.c.jj 2004-01-21 11:45:20.000000000 +0100 ++++ gcc/gcc.c 2004-01-21 11:56:46.000000000 +0100 +@@ -352,6 +352,9 @@ static void init_gcc_specs (struct obsta + #if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX) + static const char *convert_filename (const char *, int, int); + #endif ++#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) ++static void retry_ice (const char *prog, const char **argv); ++#endif + + static const char *if_exists_spec_function (int, const char **); + static const char *if_exists_else_spec_function (int, const char **); +@@ -2753,7 +2756,7 @@ execute (void) + if (commands[i].pid == -1) + pfatal_pexecute (errmsg_fmt, errmsg_arg); + +- if (string != commands[i].prog) ++ if (i && string != commands[i].prog) + free ((void *) string); + } + +@@ -2831,6 +2834,17 @@ See %s for instructions.", + else if (WIFEXITED (status) + && WEXITSTATUS (status) >= MIN_FATAL_STATUS) + { ++#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) ++ /* For ICEs in cc1, cc1obj, cc1plus see if it is ++ reproducible or not. */ ++ char *p; ++ if (WEXITSTATUS (status) == ICE_EXIT_CODE ++ && j == 0 ++ && (p = strrchr (commands[j].argv[0], DIR_SEPARATOR)) ++ && ! strncmp (p + 1, "cc1", 3)) ++ retry_ice (commands[j].prog, commands[j].argv); ++#endif ++ + if (WEXITSTATUS (status) > greatest_status) + greatest_status = WEXITSTATUS (status); + ret_code = -1; +@@ -2842,6 +2856,10 @@ See %s for instructions.", + break; + } + } ++ ++ if (commands[0].argv[0] != commands[0].prog) ++ free ((PTR) commands[0].argv[0]); ++ + return ret_code; + } + } +@@ -5809,6 +5827,224 @@ give_switch (int switchnum, int omit_fir + switches[switchnum].validated = 1; + } + ++#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) ++#define RETRY_ICE_ATTEMPTS 2 ++ ++static void ++retry_ice (const char *prog, const char **argv) ++{ ++ int nargs, out_arg = -1, quiet = 0, attempt; ++ int pid, retries, sleep_interval; ++ const char **new_argv; ++ char *temp_filenames[RETRY_ICE_ATTEMPTS * 2 + 2]; ++ ++ if (input_filename == NULL || ! strcmp (input_filename, "-")) ++ return; ++ ++ for (nargs = 0; argv[nargs] != NULL; ++nargs) ++ /* Only retry compiler ICEs, not preprocessor ones. */ ++ if (! strcmp (argv[nargs], "-E")) ++ return; ++ else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o') ++ { ++ if (out_arg == -1) ++ out_arg = nargs; ++ else ++ return; ++ } ++ /* If the compiler is going to output any time information, ++ it might varry between invocations. */ ++ else if (! strcmp (argv[nargs], "-quiet")) ++ quiet = 1; ++ else if (! strcmp (argv[nargs], "-ftime-report")) ++ return; ++ ++ if (out_arg == -1 || !quiet) ++ return; ++ ++ memset (temp_filenames, '\0', sizeof (temp_filenames)); ++ new_argv = alloca ((nargs + 3) * sizeof (const char *)); ++ memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *)); ++ new_argv[nargs++] = "-frandom-seed=0"; ++ new_argv[nargs] = NULL; ++ if (new_argv[out_arg][2] == '\0') ++ new_argv[out_arg + 1] = "-"; ++ else ++ new_argv[out_arg] = "-o-"; ++ ++ for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS + 1; ++attempt) ++ { ++ int fd; ++ int status; ++ ++ temp_filenames[attempt * 2] = make_temp_file (".out"); ++ temp_filenames[attempt * 2 + 1] = make_temp_file (".err"); ++ ++ if (attempt == RETRY_ICE_ATTEMPTS) ++ { ++ int i; ++ int fd1, fd2; ++ struct stat st1, st2; ++ size_t n, len; ++ char *buf; ++ ++ buf = xmalloc (8192); ++ ++ for (i = 0; i < 2; ++i) ++ { ++ fd1 = open (temp_filenames[i], O_RDONLY); ++ fd2 = open (temp_filenames[2 + i], O_RDONLY); ++ ++ if (fd1 < 0 || fd2 < 0) ++ { ++ i = -1; ++ close (fd1); ++ close (fd2); ++ break; ++ } ++ ++ if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0) ++ { ++ i = -1; ++ close (fd1); ++ close (fd2); ++ break; ++ } ++ ++ if (st1.st_size != st2.st_size) ++ { ++ close (fd1); ++ close (fd2); ++ break; ++ } ++ ++ len = 0; ++ for (n = st1.st_size; n; n -= len) ++ { ++ len = n; ++ if (len > 4096) ++ len = 4096; ++ ++ if (read (fd1, buf, len) != (int) len ++ || read (fd2, buf + 4096, len) != (int) len) ++ { ++ i = -1; ++ break; ++ } ++ ++ if (memcmp (buf, buf + 4096, len) != 0) ++ break; ++ } ++ ++ close (fd1); ++ close (fd2); ++ ++ if (n) ++ break; ++ } ++ ++ free (buf); ++ if (i == -1) ++ break; ++ ++ if (i != 2) ++ { ++ notice ("The bug is not reproducible, so it is likely a hardware or OS problem.\n"); ++ break; ++ } ++ ++ fd = open (temp_filenames[attempt * 2], O_RDWR); ++ if (fd < 0) ++ break; ++ write (fd, "//", 2); ++ for (i = 0; i < nargs; i++) ++ { ++ write (fd, " ", 1); ++ write (fd, new_argv[i], strlen (new_argv[i])); ++ } ++ write (fd, "\n", 1); ++ new_argv[nargs] = "-E"; ++ new_argv[nargs + 1] = NULL; ++ } ++ ++ /* Fork a subprocess; wait and retry if it fails. */ ++ sleep_interval = 1; ++ pid = -1; ++ for (retries = 0; retries < 4; retries++) ++ { ++ pid = fork (); ++ if (pid >= 0) ++ break; ++ sleep (sleep_interval); ++ sleep_interval *= 2; ++ } ++ ++ if (pid < 0) ++ break; ++ else if (pid == 0) ++ { ++ if (attempt != RETRY_ICE_ATTEMPTS) ++ fd = open (temp_filenames[attempt * 2], O_RDWR); ++ if (fd < 0) ++ exit (-1); ++ if (fd != 1) ++ { ++ close (1); ++ dup (fd); ++ close (fd); ++ } ++ ++ fd = open (temp_filenames[attempt * 2 + 1], O_RDWR); ++ if (fd < 0) ++ exit (-1); ++ if (fd != 2) ++ { ++ close (2); ++ dup (fd); ++ close (fd); ++ } ++ ++ if (prog == new_argv[0]) ++ execvp (prog, (char *const *) new_argv); ++ else ++ execv (new_argv[0], (char *const *) new_argv); ++ exit (-1); ++ } ++ ++ if (waitpid (pid, &status, 0) < 0) ++ break; ++ ++ if (attempt < RETRY_ICE_ATTEMPTS ++ && (! WIFEXITED (status) || WEXITSTATUS (status) != ICE_EXIT_CODE)) ++ { ++ notice ("The bug is not reproducible, so it is likely a hardware or OS problem.\n"); ++ break; ++ } ++ else if (attempt == RETRY_ICE_ATTEMPTS) ++ { ++ close (fd); ++ if (WIFEXITED (status) ++ && WEXITSTATUS (status) == SUCCESS_EXIT_CODE) ++ { ++ notice ("Preprocessed source stored into %s file, please attach this to your bugreport.\n", ++ temp_filenames[attempt * 2]); ++ /* Make sure it is not deleted. */ ++ free (temp_filenames[attempt * 2]); ++ temp_filenames[attempt * 2] = NULL; ++ break; ++ } ++ } ++ } ++ ++ for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS * 2 + 2; attempt++) ++ if (temp_filenames[attempt]) ++ { ++ unlink (temp_filenames[attempt]); ++ free (temp_filenames[attempt]); ++ } ++} ++#endif ++ + /* Search for a file named NAME trying various prefixes including the + user's -B prefix and some standard ones. + Return the absolute file name found. If nothing is found, return NAME. */ +--- gcc/diagnostic.c.jj 2003-10-01 12:09:21.000000000 +0200 ++++ gcc/diagnostic.c 2004-01-21 11:54:47.000000000 +0100 +@@ -272,14 +272,14 @@ diagnostic_action_after_output (diagnost + real_abort (); + + fnotice (stderr, bug_report_request, bug_report_url); +- exit (FATAL_EXIT_CODE); ++ exit (ICE_EXIT_CODE); + + case DK_FATAL: + if (context->abort_on_error) + real_abort (); + + fnotice (stderr, "compilation terminated.\n"); +- exit (FATAL_EXIT_CODE); ++ exit (ICE_EXIT_CODE); + + default: + real_abort (); +@@ -571,7 +571,7 @@ error_recursion (diagnostic_context *con + fnotice (stderr, + "Internal compiler error: Error reporting routines re-entered.\n"); + fnotice (stderr, bug_report_request, bug_report_url); +- exit (FATAL_EXIT_CODE); ++ exit (ICE_EXIT_CODE); + } + + /* Report an internal compiler error in a friendly manner. This is diff --git a/SOURCES/gcc34-java-jnilink.patch b/SOURCES/gcc34-java-jnilink.patch new file mode 100644 index 0000000..cefa875 --- /dev/null +++ b/SOURCES/gcc34-java-jnilink.patch @@ -0,0 +1,34 @@ +2005-11-21 Jakub Jelinek + + * jni/classpath/jnilink.c (LINK_ReallyLinkClass, + LINK_ReallyLinkKnownClass): Add dummy functions. + +--- libjava/jni/classpath/jnilink.c.jj 2005-11-21 15:36:51.000000000 +0100 ++++ libjava/jni/classpath/jnilink.c 2005-11-21 18:12:35.000000000 +0100 +@@ -45,6 +45,26 @@ exception statement from your version. * + #define GETCLASS(c) *(jclass*)(c) + + JNIEXPORT jclass JNICALL ++LINK_ReallyLinkClass (JNIEnv * env, linkedClass * c, char * name) ++{ ++ (void) env; ++ (void) c; ++ (void) name; ++ abort (); ++ return NULL; ++} ++ ++JNIEXPORT jclass JNICALL ++LINK_ReallyLinkKnownClass (JNIEnv * env, linkedClass * c, jclass newClass) ++{ ++ (void) env; ++ (void) c; ++ (void) newClass; ++ abort (); ++ return NULL; ++} ++ ++JNIEXPORT jclass JNICALL + LINK_RelinkClass (JNIEnv * env, linkedClass * c, char * name) { + jclass found; + LINK_UnlinkClass(env,*c); diff --git a/SOURCES/gcc34-java-nomulti.patch b/SOURCES/gcc34-java-nomulti.patch new file mode 100644 index 0000000..255feaf --- /dev/null +++ b/SOURCES/gcc34-java-nomulti.patch @@ -0,0 +1,25 @@ +--- libjava/configure.in.jj 2004-08-16 21:13:29.000000000 +0200 ++++ libjava/configure.in 2004-08-21 11:44:59.020755542 +0200 +@@ -367,6 +367,10 @@ use_gtk_awt="" + TOOLKIT= + AC_SUBST(TOOLKIT) + ++if test -n "${with_multisubdir}"; then ++ peerlibs=no ++fi ++ + for peer in $peerlibs ; do + case $peer in + xlib) +--- libjava/configure.jj 2004-08-16 21:22:14.000000000 +0200 ++++ libjava/configure 2004-08-21 11:45:16.260738060 +0200 +@@ -4118,6 +4118,9 @@ use_gtk_awt="" + # The default toolkit to use is the first one specified. + TOOLKIT= + ++if test -n "${with_multisubdir}"; then ++ peerlibs=no ++fi + + for peer in $peerlibs ; do + case $peer in diff --git a/SOURCES/gcc34-java-zoneinfo.patch b/SOURCES/gcc34-java-zoneinfo.patch new file mode 100644 index 0000000..45e4bed --- /dev/null +++ b/SOURCES/gcc34-java-zoneinfo.patch @@ -0,0 +1,3024 @@ +2007-02-24 Jakub Jelinek + + * java/util/TimeZone.java (getDefaultDisplayName): Don't + check if TimeZone is instanceof SimpleTimeZone. + +2007-02-23 Jakub Jelinek + + PR libgcj/17002 + PR classpath/28550 + * java/lang/System.java: Add gnu.java.util.zoneinfo.dir to comments. + * posix.cc (_Jv_platform_initProperties): Set + gnu.java.util.zoneinfo.dir. + * Makefile.am (ordinary_java_source_files): Add + gnu/java/util/ZoneInfo.java. + * Makefile.in: Regenerated. + * java/util/Date.java (parse): Properly parse 09:01:02 as + hours/minutes/seconds, not as hours/minutes/year. + * java/util/SimpleTimeZone.java (getOffset): Handle properly + millis + dstOffset overflowing into the next day. + * java/util/TimeZone.java (zoneinfo_dir, availableIDs, aliases0): New + static fields. + (timezones): Remove synchronized keyword. Set zoneinfo_dir. + If non-null, set up aliases0 and don't put anything into + timezones0. + (defaultZone): Call getTZEnvVar to try TZ env var. + Try to read /etc/localtime using ZoneInfo.readTZFile. + Call getDefaultTimeZone instead of getTimeZone. + (getDefaultTimeZone, getDateParams, parseTime): New private methods. + (getTimeZoneInternal): New private method. + (getTimeZone): Do the custom ID checking first, canonicalize + ID for custom IDs as required by documentation. Call + getTimeZoneInternal to handle the rest. + (getAvailableIDs(int)): Add locking. Handle zoneinfo_dir != null. + (getAvailableIDs(File,String,ArrayList)): New private method. + (getAvailableIDs()): Add locking. Handle zoneinfo_dir != null. + (readSysconfigClockFile): New static method. + (getTZEnvVar): New native method. + * java/util/natTimeZone.cc: Include stdlib.h. + (getTZEnvVar): New method. + * gnu/java/util/ZoneInfo.java: New file. + * java/util/GregorianCalendar.java + (GregorianCalendar): Call clear before set in the constructors that + don't initialize it to current time. + +2007-02-09 Jakub Jelinek + + PR 23566 + * java/util/TimeZone.java (timezones): Regenerate from tzdata2007a. + +2005-02-21 Jeroen Frijters + + * java/util/GregorianCalendar.java + (GregorianCalendar): Chained constructors to a (new) + common constructor. + +--- libjava/Makefile.am.jj 2006-10-05 00:38:22.000000000 +0200 ++++ libjava/Makefile.am 2007-02-23 13:44:59.000000000 +0100 +@@ -2382,6 +2382,7 @@ gnu/java/text/SentenceBreakIterator.java + gnu/java/text/WordBreakIterator.java \ + gnu/java/util/DoubleEnumeration.java \ + gnu/java/util/EmptyEnumeration.java \ ++gnu/java/util/ZoneInfo.java \ + gnu/java/util/prefs/MemoryBasedFactory.java \ + gnu/java/util/prefs/NodeReader.java \ + gnu/java/util/prefs/MemoryBasedPreferences.java \ +--- libjava/Makefile.in.jj 2006-10-05 00:38:22.000000000 +0200 ++++ libjava/Makefile.in 2007-02-23 13:46:07.000000000 +0100 +@@ -2073,6 +2073,7 @@ gnu/java/text/SentenceBreakIterator.java + gnu/java/text/WordBreakIterator.java \ + gnu/java/util/DoubleEnumeration.java \ + gnu/java/util/EmptyEnumeration.java \ ++gnu/java/util/ZoneInfo.java \ + gnu/java/util/prefs/MemoryBasedFactory.java \ + gnu/java/util/prefs/NodeReader.java \ + gnu/java/util/prefs/MemoryBasedPreferences.java \ +@@ -3331,6 +3332,7 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_D + .deps/gnu/java/text/WordBreakIterator.P \ + .deps/gnu/java/util/DoubleEnumeration.P \ + .deps/gnu/java/util/EmptyEnumeration.P \ ++.deps/gnu/java/util/ZoneInfo.P \ + .deps/gnu/java/util/prefs/FileBasedFactory.P \ + .deps/gnu/java/util/prefs/MemoryBasedFactory.P \ + .deps/gnu/java/util/prefs/MemoryBasedPreferences.P \ +--- libjava/java/util/GregorianCalendar.java.jj 2006-10-05 00:38:18.000000000 +0200 ++++ libjava/java/util/GregorianCalendar.java 2007-02-23 19:30:20.000000000 +0100 +@@ -121,6 +121,13 @@ public class GregorianCalendar extends C + this(TimeZone.getDefault(), locale); + } + ++ private GregorianCalendar(TimeZone zone, Locale locale, boolean unused) ++ { ++ super(zone, locale); ++ ResourceBundle rb = getBundle(locale); ++ gregorianCutover = ((Date) rb.getObject("gregorianCutOver")).getTime(); ++ } ++ + /** + * Constructs a new GregorianCalender representing the current + * time with the given time zone and the given locale. +@@ -129,9 +136,7 @@ public class GregorianCalendar extends C + */ + public GregorianCalendar(TimeZone zone, Locale locale) + { +- super(zone, locale); +- ResourceBundle rb = getBundle(locale); +- gregorianCutover = ((Date) rb.getObject("gregorianCutOver")).getTime(); ++ this(zone, locale, false); + setTimeInMillis(System.currentTimeMillis()); + } + +@@ -144,7 +149,8 @@ public class GregorianCalendar extends C + */ + public GregorianCalendar(int year, int month, int day) + { +- super(); ++ this(TimeZone.getDefault(), Locale.getDefault(), false); ++ clear(); + set(year, month, day); + } + +@@ -159,7 +165,8 @@ public class GregorianCalendar extends C + */ + public GregorianCalendar(int year, int month, int day, int hour, int minute) + { +- super(); ++ this(TimeZone.getDefault(), Locale.getDefault(), false); ++ clear(); + set(year, month, day, hour, minute); + } + +@@ -176,7 +183,8 @@ public class GregorianCalendar extends C + public GregorianCalendar(int year, int month, int day, + int hour, int minute, int second) + { +- super(); ++ this(TimeZone.getDefault(), Locale.getDefault(), false); ++ clear(); + set(year, month, day, hour, minute, second); + } + +--- libjava/java/util/SimpleTimeZone.java.jj 2006-10-05 00:38:18.000000000 +0200 ++++ libjava/java/util/SimpleTimeZone.java 2007-02-23 14:38:01.000000000 +0100 +@@ -460,16 +460,34 @@ public class SimpleTimeZone extends Time + int daylightSavings = 0; + if (useDaylight && era == GregorianCalendar.AD && year >= startYear) + { ++ int orig_year = year; + // This does only work for Gregorian calendars :-( + // This is mainly because setStartYear doesn't take an era. + + boolean afterStart = !isBefore(year, month, day, dayOfWeek, millis, + startMode, startMonth, + startDay, startDayOfWeek, startTime); ++ millis += dstSavings; ++ if (millis >= 24 * 60 * 60 * 1000) ++ { ++ millis -= 24 * 60 * 60 * 1000; ++ dayOfWeek = (dayOfWeek % 7) + 1; ++ if (++day > getDaysInMonth(month, year)) ++ { ++ day = 1; ++ if (month++ == Calendar.DECEMBER) ++ { ++ month = Calendar.JANUARY; ++ year++; ++ } ++ } ++ } + boolean beforeEnd = isBefore(year, month, day, dayOfWeek, millis, + endMode, endMonth, + endDay, endDayOfWeek, endTime); + ++ if (orig_year != year) ++ afterStart = false; + if (startMonth < endMonth) + { + // use daylight savings, if the date is after the start of +--- libjava/java/util/Date.java.jj 2006-10-05 00:38:18.000000000 +0200 ++++ libjava/java/util/Date.java 2007-02-23 14:38:01.000000000 +0100 +@@ -411,6 +411,7 @@ public class Date implements Cloneable, + } + else if (firstch >= '0' && firstch <= '9') + { ++ int lastPunct = -1; + while (tok != null && tok.length() > 0) + { + int punctOffset = tok.length(); +@@ -448,6 +449,13 @@ public class Date implements Cloneable, + else + minute = num; + } ++ else if (lastPunct == ':' && hour >= 0 && (minute < 0 || second < 0)) ++ { ++ if (minute < 0) ++ minute = num; ++ else ++ second = num; ++ } + else if ((num >= 70 + && (punct == ' ' || punct == ',' + || punct == '/' || punct < 0)) +@@ -486,6 +494,7 @@ public class Date implements Cloneable, + tok = null; + else + tok = tok.substring(punctOffset + 1); ++ lastPunct = punct; + } + } + else if (firstch >= 'A' && firstch <= 'Z') +--- libjava/java/util/natTimeZone.cc.jj 2006-10-05 00:38:18.000000000 +0200 ++++ libjava/java/util/natTimeZone.cc 2007-02-23 15:14:38.000000000 +0100 +@@ -18,6 +18,7 @@ details. */ + #include + #include + ++#include + #include + + #if TIME_WITH_SYS_TIME +@@ -168,3 +169,12 @@ java::util::TimeZone::getDefaultTimeZone + // If all else fails, return null. + return NULL; + } ++ ++jstring ++java::util::TimeZone::getTZEnvVar () ++{ ++ const char *tzenv = ::getenv ("TZ"); ++ if (tzenv == NULL) ++ return NULL; ++ return JvNewStringUTF (tzenv); ++} +--- libjava/java/util/TimeZone.java.jj 2006-10-05 00:38:18.000000000 +0200 ++++ libjava/java/util/TimeZone.java 2007-02-23 15:10:51.000000000 +0100 +@@ -38,8 +38,15 @@ exception statement from your version. * + + + package java.util; +-import java.text.DateFormatSymbols; + import gnu.classpath.Configuration; ++import gnu.java.util.ZoneInfo; ++import java.io.BufferedInputStream; ++import java.io.BufferedReader; ++import java.io.File; ++import java.io.FileInputStream; ++import java.io.InputStreamReader; ++import java.io.IOException; ++import java.text.DateFormatSymbols; + + /** + * This class represents a time zone offset and handles daylight savings. +@@ -94,14 +101,72 @@ public abstract class TimeZone implement + System.loadLibrary("javautil"); + } + String tzid = System.getProperty("user.timezone"); +- ++ ++ if (tzid == null) ++ { ++ tzid = getTZEnvVar(); ++ if (tzid != null && tzid.equals("")) ++ tzid = null; ++ } ++ ++ if (tzid == null) ++ { ++ TimeZone zone = ZoneInfo.readTZFile((String) null, "/etc/localtime"); ++ if (zone != null) ++ { ++ // Try to find a more suitable ID for the /etc/localtime ++ // timezone. ++ // Sometimes /etc/localtime is a symlink to some ++ // /usr/share/zoneinfo/ file. ++ String id = null; ++ try ++ { ++ id = new File("/etc/localtime").getCanonicalPath(); ++ if (id != null) ++ { ++ String zoneinfo_dir ++ = System.getProperty("gnu.java.util.zoneinfo.dir"); ++ if (zoneinfo_dir != null) ++ zoneinfo_dir ++ = new File(zoneinfo_dir ++ + File.separatorChar).getCanonicalPath(); ++ if (zoneinfo_dir != null && id.startsWith(zoneinfo_dir)) ++ { ++ int pos = zoneinfo_dir.length(); ++ while (pos < id.length() ++ && id.charAt(pos) == File.separatorChar) ++ pos++; ++ if (pos < id.length()) ++ id = id.substring(pos); ++ else ++ id = null; ++ } ++ else ++ id = null; ++ } ++ } ++ catch (IOException ioe) ++ { ++ id = null; ++ } ++ ++ if (id == null) ++ id = readSysconfigClockFile("/etc/sysconfig/clock"); ++ ++ if (id != null) ++ zone.setID(id); ++ defaultZone0 = zone; ++ return defaultZone0; ++ } ++ } ++ + if (tzid == null) + tzid = getDefaultTimeZoneId(); + + if (tzid == null) + tzid = "GMT"; + +- defaultZone0 = getTimeZone(tzid); ++ defaultZone0 = getDefaultTimeZone(tzid); + } + return defaultZone0; + } +@@ -110,18 +175,76 @@ public abstract class TimeZone implement + private static final long serialVersionUID = 3581463369166924961L; + + /** +- * Hashtable for timezones by ID. ++ * Flag whether zoneinfo data should be used, ++ * otherwise builtin timezone data will be provided. ++ */ ++ private static String zoneinfo_dir; ++ ++ /** ++ * Cached copy of getAvailableIDs(). ++ */ ++ private static String[] availableIDs = null; ++ ++ /** ++ * JDK 1.1.x compatibility aliases. ++ */ ++ private static Hashtable aliases0; ++ ++ /** ++ * Hashtable for timezones by ID. + */ + private static Hashtable timezones0; + /* initialize this static field lazily to overhead if + * it is not needed: + */ +- private static synchronized Hashtable timezones() { ++ private static Hashtable timezones() { + if (timezones0==null) + { + Hashtable timezones = new Hashtable(); + timezones0 = timezones; + ++ zoneinfo_dir = System.getProperty("gnu.java.util.zoneinfo.dir"); ++ if (zoneinfo_dir != null && !new File(zoneinfo_dir).isDirectory()) ++ zoneinfo_dir = null; ++ ++ if (zoneinfo_dir != null) ++ { ++ aliases0 = new Hashtable(); ++ ++ // These deprecated aliases for JDK 1.1.x compatibility ++ // should take precedence over data files read from ++ // /usr/share/zoneinfo. ++ aliases0.put("ACT", "Australia/Darwin"); ++ aliases0.put("AET", "Australia/Sydney"); ++ aliases0.put("AGT", "America/Argentina/Buenos_Aires"); ++ aliases0.put("ART", "Africa/Cairo"); ++ aliases0.put("AST", "America/Juneau"); ++ aliases0.put("BST", "Asia/Colombo"); ++ aliases0.put("CAT", "Africa/Gaborone"); ++ aliases0.put("CNT", "America/St_Johns"); ++ aliases0.put("CST", "CST6CDT"); ++ aliases0.put("CTT", "Asia/Brunei"); ++ aliases0.put("EAT", "Indian/Comoro"); ++ aliases0.put("ECT", "CET"); ++ aliases0.put("EST", "EST5EDT"); ++ aliases0.put("EST5", "EST5EDT"); ++ aliases0.put("IET", "EST5EDT"); ++ aliases0.put("IST", "Asia/Calcutta"); ++ aliases0.put("JST", "Asia/Seoul"); ++ aliases0.put("MIT", "Pacific/Niue"); ++ aliases0.put("MST", "MST7MDT"); ++ aliases0.put("MST7", "MST7MDT"); ++ aliases0.put("NET", "Indian/Mauritius"); ++ aliases0.put("NST", "Pacific/Auckland"); ++ aliases0.put("PLT", "Indian/Kerguelen"); ++ aliases0.put("PNT", "MST7MDT"); ++ aliases0.put("PRT", "America/Anguilla"); ++ aliases0.put("PST", "PST8PDT"); ++ aliases0.put("SST", "Pacific/Ponape"); ++ aliases0.put("VST", "Asia/Bangkok"); ++ return timezones; ++ } ++ + TimeZone tz; + // Automatically generated by scripts/timezones.pl + // XXX - Should we read this data from a file? +@@ -133,8 +256,8 @@ public abstract class TimeZone implement + timezones0.put("Pacific/Pago_Pago", tz); + tz = new SimpleTimeZone + (-10000 * 3600, "America/Adak", +- Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600); + timezones0.put("America/Adak", tz); + tz = new SimpleTimeZone(-10000 * 3600, "HST"); + timezones0.put("HST", tz); +@@ -147,8 +270,8 @@ public abstract class TimeZone implement + timezones0.put("Pacific/Marquesas", tz); + tz = new SimpleTimeZone + (-9000 * 3600, "AST", +- Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600); + timezones0.put("AST", tz); + timezones0.put("America/Anchorage", tz); + timezones0.put("America/Juneau", tz); +@@ -157,33 +280,29 @@ public abstract class TimeZone implement + tz = new SimpleTimeZone(-9000 * 3600, "Pacific/Gambier"); + timezones0.put("Pacific/Gambier", tz); + tz = new SimpleTimeZone +- (-8000 * 3600, "PST", ++ (-8000 * 3600, "America/Tijuana", + Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600, + Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ timezones0.put("America/Tijuana", tz); ++ tz = new SimpleTimeZone ++ (-8000 * 3600, "PST", ++ Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600); + timezones0.put("PST", tz); + timezones0.put("PST8PDT", tz); + timezones0.put("America/Dawson", tz); + timezones0.put("America/Los_Angeles", tz); +- timezones0.put("America/Tijuana", tz); + timezones0.put("America/Vancouver", tz); + timezones0.put("America/Whitehorse", tz); + timezones0.put("US/Pacific-New", tz); + tz = new SimpleTimeZone(-8000 * 3600, "Pacific/Pitcairn"); + timezones0.put("Pacific/Pitcairn", tz); + tz = new SimpleTimeZone +- (-7000 * 3600, "MST", ++ (-7000 * 3600, "America/Chihuahua", + Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600, + Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); +- timezones0.put("MST", tz); +- timezones0.put("MST7MDT", tz); +- timezones0.put("America/Boise", tz); + timezones0.put("America/Chihuahua", tz); +- timezones0.put("America/Denver", tz); +- timezones0.put("America/Edmonton", tz); +- timezones0.put("America/Inuvik", tz); + timezones0.put("America/Mazatlan", tz); +- timezones0.put("America/Shiprock", tz); +- timezones0.put("America/Yellowknife", tz); + tz = new SimpleTimeZone(-7000 * 3600, "MST7"); + timezones0.put("MST7", tz); + timezones0.put("PNT", tz); +@@ -191,20 +310,26 @@ public abstract class TimeZone implement + timezones0.put("America/Hermosillo", tz); + timezones0.put("America/Phoenix", tz); + tz = new SimpleTimeZone +- (-6000 * 3600, "CST", ++ (-7000 * 3600, "MST", ++ Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600); ++ timezones0.put("MST", tz); ++ timezones0.put("MST7MDT", tz); ++ timezones0.put("America/Boise", tz); ++ timezones0.put("America/Cambridge_Bay", tz); ++ timezones0.put("America/Denver", tz); ++ timezones0.put("America/Edmonton", tz); ++ timezones0.put("America/Inuvik", tz); ++ timezones0.put("America/Shiprock", tz); ++ timezones0.put("America/Yellowknife", tz); ++ tz = new SimpleTimeZone ++ (-6000 * 3600, "America/Cancun", + Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600, + Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); +- timezones0.put("CST", tz); +- timezones0.put("CST6CDT", tz); +- timezones0.put("America/Cambridge_Bay", tz); + timezones0.put("America/Cancun", tz); +- timezones0.put("America/Chicago", tz); +- timezones0.put("America/Menominee", tz); + timezones0.put("America/Merida", tz); + timezones0.put("America/Mexico_City", tz); + timezones0.put("America/Monterrey", tz); +- timezones0.put("America/Rainy_River", tz); +- timezones0.put("America/Winnipeg", tz); + tz = new SimpleTimeZone(-6000 * 3600, "America/Belize"); + timezones0.put("America/Belize", tz); + timezones0.put("America/Costa_Rica", tz); +@@ -216,57 +341,81 @@ public abstract class TimeZone implement + timezones0.put("America/Tegucigalpa", tz); + timezones0.put("Pacific/Galapagos", tz); + tz = new SimpleTimeZone ++ (-6000 * 3600, "CST", ++ Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600); ++ timezones0.put("CST", tz); ++ timezones0.put("CST6CDT", tz); ++ timezones0.put("America/Chicago", tz); ++ timezones0.put("America/Indiana/Knox", tz); ++ timezones0.put("America/Indiana/Petersburg", tz); ++ timezones0.put("America/Indiana/Vincennes", tz); ++ timezones0.put("America/Menominee", tz); ++ timezones0.put("America/North_Dakota/Center", tz); ++ timezones0.put("America/North_Dakota/New_Salem", tz); ++ timezones0.put("America/Rainy_River", tz); ++ timezones0.put("America/Rankin_Inlet", tz); ++ timezones0.put("America/Winnipeg", tz); ++ tz = new SimpleTimeZone + (-6000 * 3600, "Pacific/Easter", +- Calendar.OCTOBER, 9, -Calendar.SUNDAY, 0 * 3600, +- Calendar.MARCH, 9, -Calendar.SUNDAY, 0 * 3600); ++ Calendar.OCTOBER, 2, Calendar.SATURDAY, 22000 * 3600, ++ Calendar.MARCH, 2, Calendar.SATURDAY, 22000 * 3600); + timezones0.put("Pacific/Easter", tz); +- tz = new SimpleTimeZone +- (-5000 * 3600, "America/Grand_Turk", +- Calendar.APRIL, 1, Calendar.SUNDAY, 0 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600); +- timezones0.put("America/Grand_Turk", tz); +- timezones0.put("America/Havana", tz); + tz = new SimpleTimeZone(-5000 * 3600, "EST5"); + timezones0.put("EST5", tz); + timezones0.put("IET", tz); ++ timezones0.put("America/Atikokan", tz); + timezones0.put("America/Bogota", tz); + timezones0.put("America/Cayman", tz); + timezones0.put("America/Eirunepe", tz); + timezones0.put("America/Guayaquil", tz); +- timezones0.put("America/Indiana/Indianapolis", tz); +- timezones0.put("America/Indiana/Knox", tz); +- timezones0.put("America/Indiana/Marengo", tz); +- timezones0.put("America/Indiana/Vevay", tz); +- timezones0.put("America/Indianapolis", tz); +- timezones0.put("America/Iqaluit", tz); + timezones0.put("America/Jamaica", tz); + timezones0.put("America/Lima", tz); + timezones0.put("America/Panama", tz); +- timezones0.put("America/Pangnirtung", tz); ++ timezones0.put("America/Rio_Branco", tz); ++ tz = new SimpleTimeZone ++ (-5000 * 3600, "America/Havana", ++ Calendar.APRIL, 1, Calendar.SUNDAY, 0 * 3600, ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 1000 * 3600); ++ timezones0.put("America/Havana", tz); ++ tz = new SimpleTimeZone ++ (-5000 * 3600, "America/Grand_Turk", ++ Calendar.APRIL, 1, Calendar.SUNDAY, 0 * 3600, ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600); ++ timezones0.put("America/Grand_Turk", tz); + timezones0.put("America/Port-au-Prince", tz); +- timezones0.put("America/Porto_Acre", tz); +- timezones0.put("America/Rankin_Inlet", tz); + tz = new SimpleTimeZone + (-5000 * 3600, "EST", +- Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600); + timezones0.put("EST", tz); + timezones0.put("EST5EDT", tz); + timezones0.put("America/Detroit", tz); ++ timezones0.put("America/Indiana/Indianapolis", tz); ++ timezones0.put("America/Indiana/Marengo", tz); ++ timezones0.put("America/Indiana/Vevay", tz); ++ timezones0.put("America/Iqaluit", tz); + timezones0.put("America/Kentucky/Louisville", tz); + timezones0.put("America/Kentucky/Monticello", tz); +- timezones0.put("America/Louisville", tz); + timezones0.put("America/Montreal", tz); + timezones0.put("America/Nassau", tz); + timezones0.put("America/New_York", tz); + timezones0.put("America/Nipigon", tz); ++ timezones0.put("America/Pangnirtung", tz); + timezones0.put("America/Thunder_Bay", tz); ++ timezones0.put("America/Toronto", tz); ++ tz = new SimpleTimeZone ++ (-4000 * 3600, "America/Asuncion", ++ Calendar.OCTOBER, 3, Calendar.SUNDAY, 0 * 3600, ++ Calendar.MARCH, 2, Calendar.SUNDAY, 0 * 3600); ++ timezones0.put("America/Asuncion", tz); + tz = new SimpleTimeZone(-4000 * 3600, "PRT"); + timezones0.put("PRT", tz); + timezones0.put("America/Anguilla", tz); + timezones0.put("America/Antigua", tz); + timezones0.put("America/Aruba", tz); + timezones0.put("America/Barbados", tz); ++ timezones0.put("America/Blanc-Sablon", tz); + timezones0.put("America/Boa_Vista", tz); + timezones0.put("America/Caracas", tz); + timezones0.put("America/Curacao", tz); +@@ -288,26 +437,23 @@ public abstract class TimeZone implement + timezones0.put("America/St_Vincent", tz); + timezones0.put("America/Tortola", tz); + tz = new SimpleTimeZone +- (-4000 * 3600, "America/Asuncion", +- Calendar.OCTOBER, 1, Calendar.SUNDAY, 0 * 3600, ++ (-4000 * 3600, "America/Campo_Grande", ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0 * 3600, + Calendar.FEBRUARY, -1, Calendar.SUNDAY, 0 * 3600); +- timezones0.put("America/Asuncion", tz); +- tz = new SimpleTimeZone +- (-4000 * 3600, "America/Cuiaba", +- Calendar.OCTOBER, 2, Calendar.SUNDAY, 0 * 3600, +- Calendar.FEBRUARY, 3, Calendar.SUNDAY, 0 * 3600); ++ timezones0.put("America/Campo_Grande", tz); + timezones0.put("America/Cuiaba", tz); + tz = new SimpleTimeZone + (-4000 * 3600, "America/Goose_Bay", +- Calendar.APRIL, 1, Calendar.SUNDAY, 60000, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 60000); ++ Calendar.MARCH, 2, Calendar.SUNDAY, 60000, ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 60000); + timezones0.put("America/Goose_Bay", tz); + tz = new SimpleTimeZone + (-4000 * 3600, "America/Glace_Bay", +- Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600); + timezones0.put("America/Glace_Bay", tz); + timezones0.put("America/Halifax", tz); ++ timezones0.put("America/Moncton", tz); + timezones0.put("America/Thule", tz); + timezones0.put("Atlantic/Bermuda", tz); + tz = new SimpleTimeZone +@@ -318,58 +464,67 @@ public abstract class TimeZone implement + timezones0.put("Antarctica/Palmer", tz); + tz = new SimpleTimeZone + (-4000 * 3600, "Atlantic/Stanley", +- Calendar.SEPTEMBER, 2, Calendar.SUNDAY, 0 * 3600, +- Calendar.APRIL, 16, -Calendar.SUNDAY, 0 * 3600); ++ Calendar.SEPTEMBER, 1, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.APRIL, 3, Calendar.SUNDAY, 2000 * 3600); + timezones0.put("Atlantic/Stanley", tz); + tz = new SimpleTimeZone + (-3500 * 3600, "CNT", +- Calendar.APRIL, 1, Calendar.SUNDAY, 60000, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 60000); ++ Calendar.MARCH, 2, Calendar.SUNDAY, 60000, ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 60000); + timezones0.put("CNT", tz); + timezones0.put("America/St_Johns", tz); + tz = new SimpleTimeZone +- (-3000 * 3600, "America/Araguaina", +- Calendar.OCTOBER, 2, Calendar.SUNDAY, 0 * 3600, +- Calendar.FEBRUARY, 3, Calendar.SUNDAY, 0 * 3600); +- timezones0.put("America/Araguaina", tz); ++ (-3000 * 3600, "America/Godthab", ++ Calendar.MARCH, 30, -Calendar.SATURDAY, 22000 * 3600, ++ Calendar.OCTOBER, 30, -Calendar.SATURDAY, 23000 * 3600); ++ timezones0.put("America/Godthab", tz); ++ tz = new SimpleTimeZone ++ (-3000 * 3600, "America/Miquelon", ++ Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 2000 * 3600); ++ timezones0.put("America/Miquelon", tz); ++ tz = new SimpleTimeZone ++ (-3000 * 3600, "America/Montevideo", ++ Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.MARCH, 2, Calendar.SUNDAY, 2000 * 3600); ++ timezones0.put("America/Montevideo", tz); ++ tz = new SimpleTimeZone ++ (-3000 * 3600, "America/Sao_Paulo", ++ Calendar.NOVEMBER, 1, Calendar.SUNDAY, 0 * 3600, ++ Calendar.FEBRUARY, -1, Calendar.SUNDAY, 0 * 3600); + timezones0.put("America/Sao_Paulo", tz); + tz = new SimpleTimeZone(-3000 * 3600, "AGT"); + timezones0.put("AGT", tz); ++ timezones0.put("America/Araguaina", tz); ++ timezones0.put("America/Argentina/Buenos_Aires", tz); ++ timezones0.put("America/Argentina/Catamarca", tz); ++ timezones0.put("America/Argentina/Cordoba", tz); ++ timezones0.put("America/Argentina/Jujuy", tz); ++ timezones0.put("America/Argentina/La_Rioja", tz); ++ timezones0.put("America/Argentina/Mendoza", tz); ++ timezones0.put("America/Argentina/Rio_Gallegos", tz); ++ timezones0.put("America/Argentina/San_Juan", tz); ++ timezones0.put("America/Argentina/Tucuman", tz); ++ timezones0.put("America/Argentina/Ushuaia", tz); ++ timezones0.put("America/Bahia", tz); + timezones0.put("America/Belem", tz); +- timezones0.put("America/Buenos_Aires", tz); +- timezones0.put("America/Catamarca", tz); + timezones0.put("America/Cayenne", tz); +- timezones0.put("America/Cordoba", tz); + timezones0.put("America/Fortaleza", tz); +- timezones0.put("America/Jujuy", tz); + timezones0.put("America/Maceio", tz); +- timezones0.put("America/Mendoza", tz); +- timezones0.put("America/Montevideo", tz); + timezones0.put("America/Paramaribo", tz); + timezones0.put("America/Recife", tz); +- timezones0.put("America/Rosario", tz); +- tz = new SimpleTimeZone +- (-3000 * 3600, "America/Godthab", +- Calendar.MARCH, 30, -Calendar.SATURDAY, 22000 * 3600, +- Calendar.OCTOBER, 30, -Calendar.SATURDAY, 22000 * 3600); +- timezones0.put("America/Godthab", tz); +- tz = new SimpleTimeZone +- (-3000 * 3600, "America/Miquelon", +- Calendar.APRIL, 1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); +- timezones0.put("America/Miquelon", tz); ++ timezones0.put("Antarctica/Rothera", tz); + tz = new SimpleTimeZone(-2000 * 3600, "America/Noronha"); + timezones0.put("America/Noronha", tz); + timezones0.put("Atlantic/South_Georgia", tz); + tz = new SimpleTimeZone + (-1000 * 3600, "America/Scoresbysund", + Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 1000 * 3600); + timezones0.put("America/Scoresbysund", tz); + timezones0.put("Atlantic/Azores", tz); + tz = new SimpleTimeZone(-1000 * 3600, "Atlantic/Cape_Verde"); + timezones0.put("Atlantic/Cape_Verde", tz); +- timezones0.put("Atlantic/Jan_Mayen", tz); + tz = new SimpleTimeZone(0 * 3600, "GMT"); + timezones0.put("GMT", tz); + timezones0.put("UTC", tz); +@@ -388,21 +543,23 @@ public abstract class TimeZone implement + timezones0.put("Africa/Nouakchott", tz); + timezones0.put("Africa/Ouagadougou", tz); + timezones0.put("Africa/Sao_Tome", tz); +- timezones0.put("Africa/Timbuktu", tz); ++ timezones0.put("America/Danmarkshavn", tz); + timezones0.put("Atlantic/Reykjavik", tz); + timezones0.put("Atlantic/St_Helena", tz); +- timezones0.put("Europe/Belfast", tz); +- timezones0.put("Europe/Dublin", tz); +- timezones0.put("Europe/London", tz); + tz = new SimpleTimeZone + (0 * 3600, "WET", + Calendar.MARCH, -1, Calendar.SUNDAY, 1000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 1000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); + timezones0.put("WET", tz); + timezones0.put("Atlantic/Canary", tz); +- timezones0.put("Atlantic/Faeroe", tz); ++ timezones0.put("Atlantic/Faroe", tz); + timezones0.put("Atlantic/Madeira", tz); ++ timezones0.put("Europe/Dublin", tz); ++ timezones0.put("Europe/Guernsey", tz); ++ timezones0.put("Europe/Isle_of_Man", tz); ++ timezones0.put("Europe/Jersey", tz); + timezones0.put("Europe/Lisbon", tz); ++ timezones0.put("Europe/London", tz); + tz = new SimpleTimeZone(1000 * 3600, "Africa/Algiers"); + timezones0.put("Africa/Algiers", tz); + timezones0.put("Africa/Bangui", tz); +@@ -416,7 +573,6 @@ public abstract class TimeZone implement + timezones0.put("Africa/Ndjamena", tz); + timezones0.put("Africa/Niamey", tz); + timezones0.put("Africa/Porto-Novo", tz); +- timezones0.put("Africa/Tunis", tz); + tz = new SimpleTimeZone + (1000 * 3600, "Africa/Windhoek", + Calendar.SEPTEMBER, 1, Calendar.SUNDAY, 2000 * 3600, +@@ -425,12 +581,14 @@ public abstract class TimeZone implement + tz = new SimpleTimeZone + (1000 * 3600, "CET", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("CET", tz); + timezones0.put("ECT", tz); + timezones0.put("MET", tz); + timezones0.put("Africa/Ceuta", tz); ++ timezones0.put("Africa/Tunis", tz); + timezones0.put("Arctic/Longyearbyen", tz); ++ timezones0.put("Atlantic/Jan_Mayen", tz); + timezones0.put("Europe/Amsterdam", tz); + timezones0.put("Europe/Andorra", tz); + timezones0.put("Europe/Belgrade", tz); +@@ -447,6 +605,7 @@ public abstract class TimeZone implement + timezones0.put("Europe/Monaco", tz); + timezones0.put("Europe/Oslo", tz); + timezones0.put("Europe/Paris", tz); ++ timezones0.put("Europe/Podgorica", tz); + timezones0.put("Europe/Prague", tz); + timezones0.put("Europe/Rome", tz); + timezones0.put("Europe/San_Marino", tz); +@@ -463,7 +622,7 @@ public abstract class TimeZone implement + tz = new SimpleTimeZone + (2000 * 3600, "ART", + Calendar.APRIL, -1, Calendar.FRIDAY, 0 * 3600, +- Calendar.SEPTEMBER, -1, Calendar.THURSDAY, 23000 * 3600); ++ Calendar.SEPTEMBER, -1, Calendar.THURSDAY, 24000 * 3600); + timezones0.put("ART", tz); + timezones0.put("Africa/Cairo", tz); + tz = new SimpleTimeZone(2000 * 3600, "CAT"); +@@ -480,13 +639,11 @@ public abstract class TimeZone implement + timezones0.put("Africa/Maseru", tz); + timezones0.put("Africa/Mbabane", tz); + timezones0.put("Africa/Tripoli", tz); +- timezones0.put("Europe/Riga", tz); +- timezones0.put("Europe/Tallinn", tz); +- timezones0.put("Europe/Vilnius", tz); ++ timezones0.put("Asia/Jerusalem", tz); + tz = new SimpleTimeZone + (2000 * 3600, "Asia/Amman", + Calendar.MARCH, -1, Calendar.THURSDAY, 0 * 3600, +- Calendar.SEPTEMBER, -1, Calendar.THURSDAY, 0 * 3600); ++ Calendar.OCTOBER, -1, Calendar.FRIDAY, 1000 * 3600); + timezones0.put("Asia/Amman", tz); + tz = new SimpleTimeZone + (2000 * 3600, "Asia/Beirut", +@@ -500,18 +657,13 @@ public abstract class TimeZone implement + timezones0.put("Asia/Damascus", tz); + tz = new SimpleTimeZone + (2000 * 3600, "Asia/Gaza", +- Calendar.APRIL, 3, Calendar.FRIDAY, 0 * 3600, ++ Calendar.APRIL, 1, 0, 0 * 3600, + Calendar.OCTOBER, 3, Calendar.FRIDAY, 0 * 3600); + timezones0.put("Asia/Gaza", tz); + tz = new SimpleTimeZone +- (2000 * 3600, "Asia/Jerusalem", +- Calendar.APRIL, 1, 0, 1000 * 3600, +- Calendar.OCTOBER, 1, 0, 1000 * 3600); +- timezones0.put("Asia/Jerusalem", tz); +- tz = new SimpleTimeZone + (2000 * 3600, "EET", + Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 4000 * 3600); + timezones0.put("EET", tz); + timezones0.put("Asia/Istanbul", tz); + timezones0.put("Asia/Nicosia", tz); +@@ -521,32 +673,36 @@ public abstract class TimeZone implement + timezones0.put("Europe/Helsinki", tz); + timezones0.put("Europe/Istanbul", tz); + timezones0.put("Europe/Kiev", tz); ++ timezones0.put("Europe/Mariehamn", tz); + timezones0.put("Europe/Nicosia", tz); ++ timezones0.put("Europe/Riga", tz); + timezones0.put("Europe/Simferopol", tz); + timezones0.put("Europe/Sofia", tz); ++ timezones0.put("Europe/Tallinn", tz); + timezones0.put("Europe/Uzhgorod", tz); ++ timezones0.put("Europe/Vilnius", tz); + timezones0.put("Europe/Zaporozhye", tz); + tz = new SimpleTimeZone + (2000 * 3600, "Europe/Kaliningrad", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Europe/Kaliningrad", tz); + timezones0.put("Europe/Minsk", tz); + tz = new SimpleTimeZone + (3000 * 3600, "Asia/Baghdad", + Calendar.APRIL, 1, 0, 3000 * 3600, +- Calendar.OCTOBER, 1, 0, 3000 * 3600); ++ Calendar.OCTOBER, 1, 0, 4000 * 3600); + timezones0.put("Asia/Baghdad", tz); + tz = new SimpleTimeZone + (3000 * 3600, "Europe/Moscow", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Europe/Moscow", tz); +- timezones0.put("Europe/Tiraspol", tz); ++ timezones0.put("Europe/Volgograd", tz); + tz = new SimpleTimeZone(3000 * 3600, "EAT"); + timezones0.put("EAT", tz); + timezones0.put("Africa/Addis_Ababa", tz); +- timezones0.put("Africa/Asmera", tz); ++ timezones0.put("Africa/Asmara", tz); + timezones0.put("Africa/Dar_es_Salaam", tz); + timezones0.put("Africa/Djibouti", tz); + timezones0.put("Africa/Kampala", tz); +@@ -566,75 +722,62 @@ public abstract class TimeZone implement + timezones0.put("Asia/Tehran", tz); + tz = new SimpleTimeZone + (4000 * 3600, "Asia/Baku", +- Calendar.MARCH, -1, Calendar.SUNDAY, 1000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 1000 * 3600); ++ Calendar.MARCH, -1, Calendar.SUNDAY, 4000 * 3600, ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 5000 * 3600); + timezones0.put("Asia/Baku", tz); + tz = new SimpleTimeZone +- (4000 * 3600, "Asia/Aqtau", +- Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600); +- timezones0.put("Asia/Aqtau", tz); +- timezones0.put("Asia/Tbilisi", tz); +- tz = new SimpleTimeZone + (4000 * 3600, "Asia/Yerevan", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Asia/Yerevan", tz); + timezones0.put("Europe/Samara", tz); + tz = new SimpleTimeZone(4000 * 3600, "NET"); + timezones0.put("NET", tz); + timezones0.put("Asia/Dubai", tz); + timezones0.put("Asia/Muscat", tz); ++ timezones0.put("Asia/Tbilisi", tz); + timezones0.put("Indian/Mahe", tz); + timezones0.put("Indian/Mauritius", tz); + timezones0.put("Indian/Reunion", tz); + tz = new SimpleTimeZone(4500 * 3600, "Asia/Kabul"); + timezones0.put("Asia/Kabul", tz); + tz = new SimpleTimeZone +- (5000 * 3600, "Asia/Aqtobe", +- Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600); +- timezones0.put("Asia/Aqtobe", tz); +- tz = new SimpleTimeZone +- (5000 * 3600, "Asia/Bishkek", +- Calendar.MARCH, -1, Calendar.SUNDAY, 2500 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2500 * 3600); +- timezones0.put("Asia/Bishkek", tz); +- tz = new SimpleTimeZone + (5000 * 3600, "Asia/Yekaterinburg", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Asia/Yekaterinburg", tz); + tz = new SimpleTimeZone(5000 * 3600, "PLT"); + timezones0.put("PLT", tz); ++ timezones0.put("Asia/Aqtau", tz); ++ timezones0.put("Asia/Aqtobe", tz); + timezones0.put("Asia/Ashgabat", tz); + timezones0.put("Asia/Dushanbe", tz); + timezones0.put("Asia/Karachi", tz); ++ timezones0.put("Asia/Oral", tz); + timezones0.put("Asia/Samarkand", tz); + timezones0.put("Asia/Tashkent", tz); +- timezones0.put("Indian/Chagos", tz); + timezones0.put("Indian/Kerguelen", tz); + timezones0.put("Indian/Maldives", tz); +- tz = new SimpleTimeZone(5500 * 3600, "IST"); ++ tz = new SimpleTimeZone(5500 * 3600, "BST"); ++ timezones0.put("BST", tz); + timezones0.put("IST", tz); + timezones0.put("Asia/Calcutta", tz); ++ timezones0.put("Asia/Colombo", tz); + tz = new SimpleTimeZone(5750 * 3600, "Asia/Katmandu"); + timezones0.put("Asia/Katmandu", tz); +- tz = new SimpleTimeZone(6000 * 3600, "BST"); +- timezones0.put("BST", tz); ++ tz = new SimpleTimeZone(6000 * 3600, "Antarctica/Mawson"); + timezones0.put("Antarctica/Mawson", tz); +- timezones0.put("Asia/Colombo", tz); ++ timezones0.put("Antarctica/Vostok", tz); ++ timezones0.put("Asia/Almaty", tz); ++ timezones0.put("Asia/Bishkek", tz); + timezones0.put("Asia/Dhaka", tz); ++ timezones0.put("Asia/Qyzylorda", tz); + timezones0.put("Asia/Thimphu", tz); +- tz = new SimpleTimeZone +- (6000 * 3600, "Asia/Almaty", +- Calendar.MARCH, -1, Calendar.SUNDAY, 0 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 0 * 3600); +- timezones0.put("Asia/Almaty", tz); ++ timezones0.put("Indian/Chagos", tz); + tz = new SimpleTimeZone + (6000 * 3600, "Asia/Novosibirsk", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Asia/Novosibirsk", tz); + timezones0.put("Asia/Omsk", tz); + tz = new SimpleTimeZone(6500 * 3600, "Asia/Rangoon"); +@@ -644,41 +787,57 @@ public abstract class TimeZone implement + timezones0.put("VST", tz); + timezones0.put("Antarctica/Davis", tz); + timezones0.put("Asia/Bangkok", tz); +- timezones0.put("Asia/Hovd", tz); + timezones0.put("Asia/Jakarta", tz); + timezones0.put("Asia/Phnom_Penh", tz); ++ timezones0.put("Asia/Pontianak", tz); + timezones0.put("Asia/Saigon", tz); + timezones0.put("Asia/Vientiane", tz); + timezones0.put("Indian/Christmas", tz); + tz = new SimpleTimeZone ++ (7000 * 3600, "Asia/Hovd", ++ Calendar.MARCH, -1, Calendar.SATURDAY, 2000 * 3600, ++ Calendar.SEPTEMBER, -1, Calendar.SATURDAY, 2000 * 3600); ++ timezones0.put("Asia/Hovd", tz); ++ tz = new SimpleTimeZone + (7000 * 3600, "Asia/Krasnoyarsk", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Asia/Krasnoyarsk", tz); + tz = new SimpleTimeZone(8000 * 3600, "CTT"); + timezones0.put("CTT", tz); + timezones0.put("Antarctica/Casey", tz); + timezones0.put("Asia/Brunei", tz); +- timezones0.put("Asia/Chungking", tz); ++ timezones0.put("Asia/Chongqing", tz); + timezones0.put("Asia/Harbin", tz); + timezones0.put("Asia/Hong_Kong", tz); + timezones0.put("Asia/Kashgar", tz); + timezones0.put("Asia/Kuala_Lumpur", tz); + timezones0.put("Asia/Kuching", tz); +- timezones0.put("Asia/Macao", tz); ++ timezones0.put("Asia/Macau", tz); ++ timezones0.put("Asia/Makassar", tz); + timezones0.put("Asia/Manila", tz); + timezones0.put("Asia/Shanghai", tz); + timezones0.put("Asia/Singapore", tz); + timezones0.put("Asia/Taipei", tz); +- timezones0.put("Asia/Ujung_Pandang", tz); +- timezones0.put("Asia/Ulaanbaatar", tz); + timezones0.put("Asia/Urumqi", tz); + timezones0.put("Australia/Perth", tz); + tz = new SimpleTimeZone + (8000 * 3600, "Asia/Irkutsk", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Asia/Irkutsk", tz); ++ tz = new SimpleTimeZone ++ (8000 * 3600, "Asia/Ulaanbaatar", ++ Calendar.MARCH, -1, Calendar.SATURDAY, 2000 * 3600, ++ Calendar.SEPTEMBER, -1, Calendar.SATURDAY, 2000 * 3600); ++ timezones0.put("Asia/Ulaanbaatar", tz); ++ tz = new SimpleTimeZone(8750 * 3600, "Australia/Eucla"); ++ timezones0.put("Australia/Eucla", tz); ++ tz = new SimpleTimeZone ++ (9000 * 3600, "Asia/Choibalsan", ++ Calendar.MARCH, -1, Calendar.SATURDAY, 2000 * 3600, ++ Calendar.SEPTEMBER, -1, Calendar.SATURDAY, 2000 * 3600); ++ timezones0.put("Asia/Choibalsan", tz); + tz = new SimpleTimeZone(9000 * 3600, "JST"); + timezones0.put("JST", tz); + timezones0.put("Asia/Dili", tz); +@@ -690,12 +849,12 @@ public abstract class TimeZone implement + tz = new SimpleTimeZone + (9000 * 3600, "Asia/Yakutsk", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Asia/Yakutsk", tz); + tz = new SimpleTimeZone + (9500 * 3600, "Australia/Adelaide", + Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Australia/Adelaide", tz); + timezones0.put("Australia/Broken_Hill", tz); + tz = new SimpleTimeZone(9500 * 3600, "ACT"); +@@ -709,33 +868,34 @@ public abstract class TimeZone implement + timezones0.put("Pacific/Port_Moresby", tz); + timezones0.put("Pacific/Saipan", tz); + timezones0.put("Pacific/Truk", tz); +- timezones0.put("Pacific/Yap", tz); + tz = new SimpleTimeZone +- (10000 * 3600, "Asia/Vladivostok", ++ (10000 * 3600, "Asia/Sakhalin", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); ++ timezones0.put("Asia/Sakhalin", tz); + timezones0.put("Asia/Vladivostok", tz); + tz = new SimpleTimeZone +- (10000 * 3600, "Australia/Hobart", ++ (10000 * 3600, "Australia/Currie", + Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600); ++ timezones0.put("Australia/Currie", tz); + timezones0.put("Australia/Hobart", tz); + tz = new SimpleTimeZone + (10000 * 3600, "AET", + Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.MARCH, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("AET", tz); + timezones0.put("Australia/Melbourne", tz); + timezones0.put("Australia/Sydney", tz); + tz = new SimpleTimeZone + (10500 * 3600, "Australia/Lord_Howe", +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, 500 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600, ++ Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, 500 * 3600); + timezones0.put("Australia/Lord_Howe", tz); + tz = new SimpleTimeZone + (11000 * 3600, "Asia/Magadan", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Asia/Magadan", tz); + tz = new SimpleTimeZone(11000 * 3600, "SST"); + timezones0.put("SST", tz); +@@ -749,7 +909,7 @@ public abstract class TimeZone implement + tz = new SimpleTimeZone + (12000 * 3600, "NST", + Calendar.OCTOBER, 1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.MARCH, 3, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.MARCH, 3, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("NST", tz); + timezones0.put("Antarctica/McMurdo", tz); + timezones0.put("Antarctica/South_Pole", tz); +@@ -757,7 +917,7 @@ public abstract class TimeZone implement + tz = new SimpleTimeZone + (12000 * 3600, "Asia/Anadyr", + Calendar.MARCH, -1, Calendar.SUNDAY, 2000 * 3600, +- Calendar.OCTOBER, -1, Calendar.SUNDAY, 2000 * 3600); ++ Calendar.OCTOBER, -1, Calendar.SUNDAY, 3000 * 3600); + timezones0.put("Asia/Anadyr", tz); + timezones0.put("Asia/Kamchatka", tz); + tz = new SimpleTimeZone(12000 * 3600, "Pacific/Fiji"); +@@ -772,7 +932,7 @@ public abstract class TimeZone implement + tz = new SimpleTimeZone + (12750 * 3600, "Pacific/Chatham", + Calendar.OCTOBER, 1, Calendar.SUNDAY, 2750 * 3600, +- Calendar.MARCH, 3, Calendar.SUNDAY, 2750 * 3600); ++ Calendar.MARCH, 3, Calendar.SUNDAY, 3750 * 3600); + timezones0.put("Pacific/Chatham", tz); + tz = new SimpleTimeZone(13000 * 3600, "Pacific/Enderbury"); + timezones0.put("Pacific/Enderbury", tz); +@@ -783,6 +943,342 @@ public abstract class TimeZone implement + return timezones0; + } + ++ /** ++ * Maps a time zone name (with optional GMT offset and daylight time ++ * zone name) to one of the known time zones. This method called ++ * with the result of System.getProperty("user.timezone") ++ * or getDefaultTimeZoneId(). Note that giving one of ++ * the standard tz data names from ftp://elsie.nci.nih.gov/pub/ is ++ * preferred. ++ * The time zone name can be given as follows: ++ * (standard zone name)[(GMT offset)[(DST zone name)[DST offset]]] ++ * ++ *

++ * If only a (standard zone name) is given (no numbers in the ++ * String) then it gets mapped directly to the TimeZone with that ++ * name, if that fails null is returned. ++ *

++ * Alternately, a POSIX-style TZ string can be given, defining the time zone: ++ * std offset dst offset,date/time,date/time ++ * See the glibc manual, or the man page for tzset for details ++ * of this format. ++ *

++ * A GMT offset is the offset to add to the local time to get GMT. ++ * If a (GMT offset) is included (either in seconds or hours) then ++ * an attempt is made to find a TimeZone name matching both the name ++ * and the offset (that doesn't observe daylight time, if the ++ * timezone observes daylight time then you must include a daylight ++ * time zone name after the offset), if that fails then a TimeZone ++ * with the given GMT offset is returned (whether or not the ++ * TimeZone observes daylight time is ignored), if that also fails ++ * the GMT TimeZone is returned. ++ *

++ * If the String ends with (GMT offset)(daylight time zone name) ++ * then an attempt is made to find a TimeZone with the given name and ++ * GMT offset that also observes (the daylight time zone name is not ++ * currently used in any other way), if that fails a TimeZone with ++ * the given GMT offset that observes daylight time is returned, if ++ * that also fails the GMT TimeZone is returned. ++ *

++ * Examples: In Chicago, the time zone id could be "CST6CDT", but ++ * the preferred name would be "America/Chicago". In Indianapolis ++ * (which does not have Daylight Savings Time) the string could be ++ * "EST5", but the preferred name would be "America/Indianapolis". ++ * The standard time zone name for The Netherlands is "Europe/Amsterdam", ++ * but can also be given as "CET-1CEST". ++ */ ++ private static TimeZone getDefaultTimeZone(String sysTimeZoneId) ++ { ++ String stdName = null; ++ int stdOffs; ++ int dstOffs; ++ try ++ { ++ int idLength = sysTimeZoneId.length(); ++ ++ int index = 0; ++ int prevIndex; ++ char c; ++ ++ // get std ++ do ++ c = sysTimeZoneId.charAt(index); ++ while (c != '+' && c != '-' && c != ',' && c != ':' ++ && ! Character.isDigit(c) && c != '\0' && ++index < idLength); ++ ++ if (index >= idLength) ++ return getTimeZoneInternal(sysTimeZoneId); ++ ++ stdName = sysTimeZoneId.substring(0, index); ++ prevIndex = index; ++ ++ // get the std offset ++ do ++ c = sysTimeZoneId.charAt(index++); ++ while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c)) ++ && index < idLength); ++ if (index < idLength) ++ index--; ++ ++ { // convert the dst string to a millis number ++ String offset = sysTimeZoneId.substring(prevIndex, index); ++ prevIndex = index; ++ ++ if (offset.charAt(0) == '+' || offset.charAt(0) == '-') ++ stdOffs = parseTime(offset.substring(1)); ++ else ++ stdOffs = parseTime(offset); ++ ++ if (offset.charAt(0) == '-') ++ stdOffs = -stdOffs; ++ ++ // TZ timezone offsets are positive when WEST of the meridian. ++ stdOffs = -stdOffs; ++ } ++ ++ // Done yet? (Format: std offset) ++ if (index >= idLength) ++ { ++ // Do we have an existing timezone with that name and offset? ++ TimeZone tz = getTimeZoneInternal(stdName); ++ if (tz != null) ++ if (tz.getRawOffset() == stdOffs) ++ return tz; ++ ++ // Custom then. ++ return new SimpleTimeZone(stdOffs, stdName); ++ } ++ ++ // get dst ++ do ++ c = sysTimeZoneId.charAt(index); ++ while (c != '+' && c != '-' && c != ',' && c != ':' ++ && ! Character.isDigit(c) && c != '\0' && ++index < idLength); ++ ++ // Done yet? (Format: std offset dst) ++ if (index >= idLength) ++ { ++ // Do we have an existing timezone with that name and offset ++ // which has DST? ++ TimeZone tz = getTimeZoneInternal(stdName); ++ if (tz != null) ++ if (tz.getRawOffset() == stdOffs && tz.useDaylightTime()) ++ return tz; ++ ++ // Custom then. ++ return new SimpleTimeZone(stdOffs, stdName); ++ } ++ ++ // get the dst offset ++ prevIndex = index; ++ do ++ c = sysTimeZoneId.charAt(index++); ++ while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c)) ++ && index < idLength); ++ if (index < idLength) ++ index--; ++ ++ if (index == prevIndex && (c == ',' || c == ';')) ++ { ++ // Missing dst offset defaults to one hour ahead of standard ++ // time. ++ dstOffs = stdOffs + 60 * 60 * 1000; ++ } ++ else ++ { // convert the dst string to a millis number ++ String offset = sysTimeZoneId.substring(prevIndex, index); ++ prevIndex = index; ++ ++ if (offset.charAt(0) == '+' || offset.charAt(0) == '-') ++ dstOffs = parseTime(offset.substring(1)); ++ else ++ dstOffs = parseTime(offset); ++ ++ if (offset.charAt(0) == '-') ++ dstOffs = -dstOffs; ++ ++ // TZ timezone offsets are positive when WEST of the meridian. ++ dstOffs = -dstOffs; ++ } ++ ++ // Done yet? (Format: std offset dst offset) ++ // FIXME: We don't support DST without a rule given. Should we? ++ if (index >= idLength) ++ { ++ // Time Zone existing with same name, dst and offsets? ++ TimeZone tz = getTimeZoneInternal(stdName); ++ if (tz != null) ++ if (tz.getRawOffset() == stdOffs && tz.useDaylightTime() ++ && tz.getDSTSavings() == (dstOffs - stdOffs)) ++ return tz; ++ ++ return new SimpleTimeZone(stdOffs, stdName); ++ } ++ ++ // get the DST rule ++ if (sysTimeZoneId.charAt(index) == ',' ++ || sysTimeZoneId.charAt(index) == ';') ++ { ++ index++; ++ int offs = index; ++ while (sysTimeZoneId.charAt(index) != ',' ++ && sysTimeZoneId.charAt(index) != ';') ++ index++; ++ String startTime = sysTimeZoneId.substring(offs, index); ++ index++; ++ String endTime = sysTimeZoneId.substring(index); ++ ++ index = startTime.indexOf('/'); ++ int startMillis; ++ int endMillis; ++ String startDate; ++ String endDate; ++ if (index != -1) ++ { ++ startDate = startTime.substring(0, index); ++ startMillis = parseTime(startTime.substring(index + 1)); ++ } ++ else ++ { ++ startDate = startTime; ++ // if time isn't given, default to 2:00:00 AM. ++ startMillis = 2 * 60 * 60 * 1000; ++ } ++ index = endTime.indexOf('/'); ++ if (index != -1) ++ { ++ endDate = endTime.substring(0, index); ++ endMillis = parseTime(endTime.substring(index + 1)); ++ } ++ else ++ { ++ endDate = endTime; ++ // if time isn't given, default to 2:00:00 AM. ++ endMillis = 2 * 60 * 60 * 1000; ++ } ++ ++ int[] start = getDateParams(startDate); ++ int[] end = getDateParams(endDate); ++ return new SimpleTimeZone(stdOffs, stdName, start[0], start[1], ++ start[2], startMillis, end[0], end[1], ++ end[2], endMillis, (dstOffs - stdOffs)); ++ } ++ } ++ ++ // FIXME: Produce a warning here? ++ catch (IndexOutOfBoundsException _) ++ { ++ } ++ catch (NumberFormatException _) ++ { ++ } ++ ++ return null; ++ } ++ ++ /** ++ * Parses and returns the params for a POSIX TZ date field, ++ * in the format int[]{ month, day, dayOfWeek }, following the ++ * SimpleTimeZone constructor rules. ++ */ ++ private static int[] getDateParams(String date) ++ { ++ int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; ++ int month; ++ ++ if (date.charAt(0) == 'M' || date.charAt(0) == 'm') ++ { ++ int day; ++ ++ // Month, week of month, day of week ++ ++ // "Mm.w.d". d is between 0 (Sunday) and 6. Week w is ++ // between 1 and 5; Week 1 is the first week in which day d ++ // occurs and Week 5 specifies the last d day in the month. ++ // Month m is between 1 and 12. ++ ++ month = Integer.parseInt(date.substring(1, date.indexOf('.'))); ++ int week = Integer.parseInt(date.substring(date.indexOf('.') + 1, ++ date.lastIndexOf('.'))); ++ int dayOfWeek = Integer.parseInt(date.substring(date.lastIndexOf('.') ++ + 1)); ++ dayOfWeek++; // Java day of week is one-based, Sunday is first day. ++ ++ if (week == 5) ++ day = -1; // last day of month is -1 in java, 5 in TZ ++ else ++ { ++ // First day of week starting on or after. For example, ++ // to specify the second Sunday of April, set month to ++ // APRIL, day-of-month to 8, and day-of-week to -SUNDAY. ++ day = (week - 1) * 7 + 1; ++ dayOfWeek = -dayOfWeek; ++ } ++ ++ month--; // Java month is zero-based. ++ return new int[] { month, day, dayOfWeek }; ++ } ++ ++ // julian day, either zero-based 0<=n<=365 (incl feb 29) ++ // or one-based 1<=n<=365 (no feb 29) ++ int julianDay; // Julian day, ++ ++ if (date.charAt(0) != 'J' || date.charAt(0) != 'j') ++ { ++ julianDay = Integer.parseInt(date.substring(1)); ++ julianDay++; // make 1-based ++ // Adjust day count to include feb 29. ++ dayCount = new int[] ++ { ++ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ++ }; ++ } ++ else ++ // 1-based julian day ++ julianDay = Integer.parseInt(date); ++ ++ int i = 11; ++ while (i > 0) ++ if (dayCount[i] < julianDay) ++ break; ++ else ++ i--; ++ julianDay -= dayCount[i]; ++ month = i; ++ return new int[] { month, julianDay, 0 }; ++ } ++ ++ /** ++ * Parses a time field hh[:mm[:ss]], returning the result ++ * in milliseconds. No leading sign. ++ */ ++ private static int parseTime(String time) ++ { ++ int millis = 0; ++ int i = 0; ++ ++ while (i < time.length()) ++ if (time.charAt(i) == ':') ++ break; ++ else ++ i++; ++ millis = 60 * 60 * 1000 * Integer.parseInt(time.substring(0, i)); ++ if (i >= time.length()) ++ return millis; ++ ++ int iprev = ++i; ++ while (i < time.length()) ++ if (time.charAt(i) == ':') ++ break; ++ else ++ i++; ++ millis += 60 * 1000 * Integer.parseInt(time.substring(iprev, i)); ++ if (i >= time.length()) ++ return millis; ++ ++ millis += 1000 * Integer.parseInt(time.substring(++i)); ++ return millis; ++ } + + /* This method returns us a time zone id string which is in the + form . +@@ -794,6 +1290,7 @@ public abstract class TimeZone implement + be EST5 + */ + private static native String getDefaultTimeZoneId(); ++ private static native String getTZEnvVar(); + + /** + * Gets the time zone offset, for current date, modified in case of +@@ -955,14 +1452,7 @@ public abstract class TimeZone implement + + private String getDefaultDisplayName(boolean dst) + { +- int offset = getRawOffset(); +- if (dst && this instanceof SimpleTimeZone) +- { +- // ugly, but this is a design failure of the API: +- // getDisplayName takes a dst parameter even though +- // TimeZone knows nothing about daylight saving offsets. +- offset += ((SimpleTimeZone) this).getDSTSavings(); +- } ++ int offset = getRawOffset() + (dst ? getDSTSavings() : 0); + + StringBuffer sb = new StringBuffer(9); + sb.append("GMT"); +@@ -1012,30 +1502,67 @@ public abstract class TimeZone implement + * @return The time zone for the identifier or GMT, if no such time + * zone exists. + */ +- // FIXME: XXX: JCL indicates this and other methods are synchronized. +- public static TimeZone getTimeZone(String ID) ++ private static TimeZone getTimeZoneInternal(String ID) + { + // First check timezones hash +- TimeZone tz = (TimeZone) timezones().get(ID); +- if (tz != null) ++ TimeZone tz = null; ++ TimeZone tznew = null; ++ for (int pass = 0; pass < 2; pass++) + { +- if (tz.getID().equals(ID)) +- return tz; ++ synchronized (TimeZone.class) ++ { ++ tz = (TimeZone) timezones().get(ID); ++ if (tz != null) ++ { ++ if (!tz.getID().equals(ID)) ++ { ++ // We always return a timezone with the requested ID. ++ // This is the same behaviour as with JDK1.2. ++ tz = (TimeZone) tz.clone(); ++ tz.setID(ID); ++ // We also save the alias, so that we return the same ++ // object again if getTimeZone is called with the same ++ // alias. ++ timezones().put(ID, tz); ++ } ++ return tz; ++ } ++ else if (tznew != null) ++ { ++ timezones().put(ID, tznew); ++ return tznew; ++ } ++ } ++ ++ if (pass == 1 || zoneinfo_dir == null) ++ return null; + +- // We always return a timezone with the requested ID. +- // This is the same behaviour as with JDK1.2. +- tz = (TimeZone) tz.clone(); +- tz.setID(ID); +- // We also save the alias, so that we return the same +- // object again if getTimeZone is called with the same +- // alias. +- timezones().put(ID, tz); +- return tz; ++ // aliases0 is never changing after first timezones(), so should ++ // be safe without synchronization. ++ String zonename = (String) aliases0.get(ID); ++ if (zonename == null) ++ zonename = ID; ++ ++ // Read the file outside of the critical section, it is expensive. ++ tznew = ZoneInfo.readTZFile (ID, zoneinfo_dir ++ + File.separatorChar + zonename); ++ if (tznew == null) ++ return null; + } + +- // See if the ID is really a GMT offset form. +- // Note that GMT is in the table so we know it is different. +- if (ID.startsWith("GMT")) ++ return null; ++ } ++ ++ /** ++ * Gets the TimeZone for the given ID. ++ * @param ID the time zone identifier. ++ * @return The time zone for the identifier or GMT, if no such time ++ * zone exists. ++ */ ++ public static TimeZone getTimeZone(String ID) ++ { ++ // Check for custom IDs first ++ if (ID.startsWith("GMT") && ID.length() > 3) + { + int pos = 3; + int offset_direction = 1; +@@ -1080,8 +1607,20 @@ public abstract class TimeZone implement + } + } + +- return new SimpleTimeZone((hour * (60 * 60 * 1000) + +- minute * (60 * 1000)) ++ // Custom IDs have to be normalized ++ StringBuffer sb = new StringBuffer(9); ++ sb.append("GMT"); ++ ++ sb.append(offset_direction >= 0 ? '+' : '-'); ++ sb.append((char) ('0' + hour / 10)); ++ sb.append((char) ('0' + hour % 10)); ++ sb.append(':'); ++ sb.append((char) ('0' + minute / 10)); ++ sb.append((char) ('0' + minute % 10)); ++ ID = sb.toString(); ++ ++ return new SimpleTimeZone((hour * (60 * 60 * 1000) ++ + minute * (60 * 1000)) + * offset_direction, ID); + } + catch (NumberFormatException e) +@@ -1089,8 +1628,11 @@ public abstract class TimeZone implement + } + } + +- // Finally, return GMT per spec +- return getTimeZone("GMT"); ++ TimeZone tz = getTimeZoneInternal(ID); ++ if (tz != null) ++ return tz; ++ ++ return new SimpleTimeZone(0, "GMT"); + } + + /** +@@ -1103,37 +1645,134 @@ public abstract class TimeZone implement + */ + public static String[] getAvailableIDs(int rawOffset) + { ++ synchronized (TimeZone.class) ++ { ++ Hashtable h = timezones(); ++ int count = 0; ++ if (zoneinfo_dir == null) ++ { ++ Iterator iter = h.entrySet().iterator(); ++ while (iter.hasNext()) ++ { ++ // Don't iterate the values, since we want to count ++ // doubled values (aliases) ++ Map.Entry entry = (Map.Entry) iter.next(); ++ if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset) ++ count++; ++ } ++ ++ String[] ids = new String[count]; ++ count = 0; ++ iter = h.entrySet().iterator(); ++ while (iter.hasNext()) ++ { ++ Map.Entry entry = (Map.Entry) iter.next(); ++ if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset) ++ ids[count++] = (String) entry.getKey(); ++ } ++ return ids; ++ } ++ } ++ ++ String[] s = getAvailableIDs(); + int count = 0; +- Iterator iter = timezones().entrySet().iterator(); +- while (iter.hasNext()) ++ for (int i = 0; i < s.length; i++) + { +- // Don't iterate the values, since we want to count +- // doubled values (aliases) +- Map.Entry entry = (Map.Entry) iter.next(); +- if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset) ++ TimeZone t = getTimeZoneInternal(s[i]); ++ if (t == null || t.getRawOffset() != rawOffset) ++ s[i] = null; ++ else + count++; + } +- + String[] ids = new String[count]; + count = 0; +- iter = timezones().entrySet().iterator(); +- while (iter.hasNext()) +- { +- Map.Entry entry = (Map.Entry) iter.next(); +- if (((TimeZone) entry.getValue()).getRawOffset() == rawOffset) +- ids[count++] = (String) entry.getKey(); +- } ++ for (int i = 0; i < s.length; i++) ++ if (s[i] != null) ++ ids[count++] = s[i]; ++ + return ids; + } + ++ private static int getAvailableIDs(File d, String prefix, ArrayList list) ++ { ++ String[] files = d.list(); ++ int count = files.length; ++ boolean top = prefix.length() == 0; ++ list.add (files); ++ for (int i = 0; i < files.length; i++) ++ { ++ if (top ++ && (files[i].equals("posix") ++ || files[i].equals("right") ++ || files[i].endsWith(".tab") ++ || aliases0.get(files[i]) != null)) ++ { ++ files[i] = null; ++ count--; ++ continue; ++ } ++ ++ File f = new File(d, files[i]); ++ if (f.isDirectory()) ++ { ++ count += getAvailableIDs(f, prefix + files[i] ++ + File.separatorChar, list) - 1; ++ files[i] = null; ++ } ++ else ++ files[i] = prefix + files[i]; ++ } ++ return count; ++ } ++ + /** + * Gets all available IDs. + * @return An array of all supported IDs. + */ + public static String[] getAvailableIDs() + { +- return (String[]) +- timezones().keySet().toArray(new String[timezones().size()]); ++ synchronized (TimeZone.class) ++ { ++ Hashtable h = timezones(); ++ if (zoneinfo_dir == null) ++ return (String[]) h.keySet().toArray(new String[h.size()]); ++ ++ if (availableIDs != null) ++ { ++ String[] ids = new String[availableIDs.length]; ++ for (int i = 0; i < availableIDs.length; i++) ++ ids[i] = availableIDs[i]; ++ return ids; ++ } ++ ++ File d = new File(zoneinfo_dir); ++ ArrayList list = new ArrayList(30); ++ int count = getAvailableIDs(d, "", list) + aliases0.size(); ++ availableIDs = new String[count]; ++ String[] ids = new String[count]; ++ ++ count = 0; ++ for (int i = 0; i < list.size(); i++) ++ { ++ String[] s = (String[]) list.get(i); ++ for (int j = 0; j < s.length; j++) ++ if (s[j] != null) ++ { ++ availableIDs[count] = s[j]; ++ ids[count++] = s[j]; ++ } ++ } ++ ++ Iterator iter = aliases0.entrySet().iterator(); ++ while (iter.hasNext()) ++ { ++ Map.Entry entry = (Map.Entry) iter.next(); ++ availableIDs[count] = (String) entry.getKey(); ++ ids[count++] = (String) entry.getKey(); ++ } ++ ++ return ids; ++ } + } + + /** +@@ -1179,4 +1818,66 @@ public abstract class TimeZone implement + return null; + } + } ++ ++ /** ++ * Tries to read the time zone name from a file. ++ * If the file cannot be read or an IOException occurs null is returned. ++ *

++ * The /etc/sysconfig/clock file is not standard, but a lot of systems ++ * have it. The file is included by shell scripts and the timezone ++ * name is defined in ZONE variable. ++ * This routine should grok it with or without quotes: ++ * ZONE=America/New_York ++ * or ++ * ZONE="Europe/London" ++ */ ++ private static String readSysconfigClockFile(String file) ++ { ++ BufferedReader br = null; ++ try ++ { ++ FileInputStream fis = new FileInputStream(file); ++ BufferedInputStream bis = new BufferedInputStream(fis); ++ br = new BufferedReader(new InputStreamReader(bis)); ++ ++ for (String line = br.readLine(); line != null; line = br.readLine()) ++ { ++ line = line.trim(); ++ if (line.length() < 8 || !line.startsWith("ZONE=")) ++ continue; ++ int posstart = 6; ++ int posend; ++ if (line.charAt(5) == '"') ++ posend = line.indexOf('"', 6); ++ else if (line.charAt(5) == '\'') ++ posend = line.indexOf('\'', 6); ++ else ++ { ++ posstart = 5; ++ posend = line.length(); ++ } ++ if (posend < 0) ++ return null; ++ return line.substring(posstart, posend); ++ } ++ return null; ++ } ++ catch (IOException ioe) ++ { ++ // Parse error, not a proper tzfile. ++ return null; ++ } ++ finally ++ { ++ try ++ { ++ if (br != null) ++ br.close(); ++ } ++ catch (IOException ioe) ++ { ++ // Error while close, nothing we can do. ++ } ++ } ++ } + } +--- libjava/java/lang/System.java.jj 2006-10-05 00:38:03.000000000 +0200 ++++ libjava/java/lang/System.java 2007-02-23 14:38:01.000000000 +0100 +@@ -355,6 +355,7 @@ public final class System + *

gnu.java.io.encoding_scheme_alias.latin?
8859_? + *
gnu.java.io.encoding_scheme_alias.UTF-8
UTF8 + *
gnu.java.io.encoding_scheme_alias.utf-8
UTF8 ++ *
gnu.java.util.zoneinfo.dir
Root of zoneinfo tree + * + * + * @return the system properties, will never be null +--- libjava/posix.cc.jj 2006-10-05 00:38:22.000000000 +0200 ++++ libjava/posix.cc 2007-02-22 23:14:41.000000000 +0100 +@@ -102,6 +102,10 @@ _Jv_platform_initProperties (java::util: + if (! tmpdir) + tmpdir = "/tmp"; + SET ("java.io.tmpdir", tmpdir); ++ const char *zoneinfodir = ::getenv("TZDATA"); ++ if (! zoneinfodir) ++ zoneinfodir = "/usr/share/zoneinfo"; ++ SET ("gnu.java.util.zoneinfo.dir", zoneinfodir); + } + + static inline void +--- libjava/gnu/java/util/ZoneInfo.java.jj 2007-02-22 23:14:22.000000000 +0100 ++++ libjava/gnu/java/util/ZoneInfo.java 2007-02-23 14:38:01.000000000 +0100 +@@ -0,0 +1,1160 @@ ++/* gnu.java.util.ZoneInfo ++ Copyright (C) 2007 Free Software Foundation, Inc. ++ ++This file is part of GNU Classpath. ++ ++GNU Classpath is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 2, or (at your option) ++any later version. ++ ++GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the ++Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++02110-1301 USA. ++ ++Linking this library statically or dynamically with other modules is ++making a combined work based on this library. Thus, the terms and ++conditions of the GNU General Public License cover the whole ++combination. ++ ++As a special exception, the copyright holders of this library give you ++permission to link this library with independent modules to produce an ++executable, regardless of the license terms of these independent ++modules, and to copy and distribute the resulting executable under ++terms of your choice, provided that you also meet, for each linked ++independent module, the terms and conditions of the license of that ++module. An independent module is a module which is not derived from ++or based on this library. If you modify this library, you may extend ++this exception to your version of the library, but you are not ++obligated to do so. If you do not wish to do so, delete this ++exception statement from your version. */ ++ ++ ++package gnu.java.util; ++ ++import java.io.BufferedInputStream; ++import java.io.DataInputStream; ++import java.io.EOFException; ++import java.io.FileInputStream; ++import java.io.InputStream; ++import java.io.IOException; ++import java.util.Calendar; ++import java.util.Date; ++import java.util.GregorianCalendar; ++import java.util.SimpleTimeZone; ++import java.util.TimeZone; ++ ++/** ++ * This class represents more advanced variant of java.util.SimpleTimeZone. ++ * It can handle zic(8) compiled transition dates plus uses a SimpleTimeZone ++ * for years beyond last precomputed transition. Before first precomputed ++ * transition it assumes no daylight saving was in effect. ++ * Timezones that never used daylight saving time should use just ++ * SimpleTimeZone instead of this class. ++ * ++ * This object is tightly bound to the Gregorian calendar. It assumes ++ * a regular seven days week, and the month lengths are that of the ++ * Gregorian Calendar. ++ * ++ * @see Calendar ++ * @see GregorianCalendar ++ * @see SimpleTimeZone ++ * @author Jakub Jelinek ++ */ ++public class ZoneInfo extends TimeZone ++{ ++ private static final int SECS_SHIFT = 22; ++ private static final long OFFSET_MASK = (1 << 21) - 1; ++ private static final int OFFSET_SHIFT = 64 - 21; ++ private static final long IS_DST = 1 << 21; ++ ++ /** ++ * The raw time zone offset in milliseconds to GMT, ignoring ++ * daylight savings. ++ * @serial ++ */ ++ private int rawOffset; ++ ++ /** ++ * Cached DST savings for the last transition rule. ++ */ ++ private int dstSavings; ++ ++ /** ++ * Cached flag whether last transition rule uses DST saving. ++ */ ++ private boolean useDaylight; ++ ++ /** ++ * Array of encoded transitions. ++ * Transition time in UTC seconds since epoch is in the most ++ * significant 64 - SECS_SHIFT bits, then one bit flag ++ * whether DST is active and the least significant bits ++ * containing offset relative to rawOffset. Both the DST ++ * flag and relative offset apply to time before the transition ++ * and after or equal to previous transition if any. ++ * The array must be sorted. ++ */ ++ private long[] transitions; ++ ++ /** ++ * SimpleTimeZone rule which applies on or after the latest ++ * transition. If the DST changes are not expresible as a ++ * SimpleTimeZone rule, then the rule should just contain ++ * the standard time and no DST time. ++ */ ++ private SimpleTimeZone lastRule; ++ ++ /** ++ * Cached GMT SimpleTimeZone object for internal use in ++ * getOffset method. ++ */ ++ private static SimpleTimeZone gmtZone = null; ++ ++ static final long serialVersionUID = -3740626706860383657L; ++ ++ /** ++ * Create a ZoneInfo with the given time offset ++ * from GMT and with daylight savings. ++ * ++ * @param rawOffset The time offset from GMT in milliseconds. ++ * @param id The identifier of this time zone. ++ * @param transitions Array of transition times in UTC seconds since ++ * Epoch in topmost 42 bits, below that 1 boolean bit whether the time ++ * before that transition used daylight saving and in bottommost 21 ++ * bits relative daylight saving offset against rawOffset in seconds ++ * that applies before this transition. ++ * @param endRule SimpleTimeZone class describing the daylight saving ++ * rules after the last transition. ++ */ ++ public ZoneInfo(int rawOffset, String id, long[] transitions, ++ SimpleTimeZone lastRule) ++ { ++ if (transitions == null || transitions.length < 1) ++ throw new IllegalArgumentException("transitions must not be null"); ++ if (lastRule == null) ++ throw new IllegalArgumentException("lastRule must not be null"); ++ this.rawOffset = rawOffset; ++ this.transitions = transitions; ++ this.lastRule = lastRule; ++ setID(id); ++ computeDSTSavings(); ++ } ++ ++ /** ++ * Gets the time zone offset, for current date, modified in case of ++ * daylight savings. This is the offset to add to UTC to get the local ++ * time. ++ * ++ * The day must be a positive number and dayOfWeek must be a positive value ++ * from Calendar. dayOfWeek is redundant, but must match the other values ++ * or an inaccurate result may be returned. ++ * ++ * @param era the era of the given date ++ * @param year the year of the given date ++ * @param month the month of the given date, 0 for January. ++ * @param day the day of month ++ * @param dayOfWeek the day of week; this must match the other fields. ++ * @param millis the millis in the day (in local standard time) ++ * @return the time zone offset in milliseconds. ++ * @throws IllegalArgumentException if arguments are incorrect. ++ */ ++ public int getOffset(int era, int year, int month, int day, int dayOfWeek, ++ int millis) ++ { ++ if (gmtZone == null) ++ gmtZone = new SimpleTimeZone(0, "GMT"); ++ ++ if (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY) ++ throw new IllegalArgumentException("dayOfWeek out of range"); ++ if (month < Calendar.JANUARY || month > Calendar.DECEMBER) ++ throw new IllegalArgumentException("month out of range:" + month); ++ ++ if (era != GregorianCalendar.AD) ++ return (int) (((transitions[0] << OFFSET_SHIFT) >> OFFSET_SHIFT) * 1000); ++ ++ GregorianCalendar cal = new GregorianCalendar((TimeZone) gmtZone); ++ cal.set(year, month, day, 0, 0, 0); ++ if (cal.get(Calendar.DAY_OF_MONTH) != day) ++ throw new IllegalArgumentException("day out of range"); ++ ++ return getOffset(cal.getTimeInMillis() - rawOffset + millis); ++ } ++ ++ private long findTransition(long secs) ++ { ++ if (secs < (transitions[0] >> SECS_SHIFT)) ++ return transitions[0]; ++ ++ if (secs >= (transitions[transitions.length-1] >> SECS_SHIFT)) ++ return Long.MAX_VALUE; ++ ++ long val = (secs + 1) << SECS_SHIFT; ++ int lo = 1; ++ int hi = transitions.length; ++ int mid = 1; ++ while (lo < hi) ++ { ++ mid = (lo + hi) / 2; ++ // secs < (transitions[mid-1] >> SECS_SHIFT) ++ if (val <= transitions[mid-1]) ++ hi = mid; ++ // secs >= (transitions[mid] >> SECS_SHIFT) ++ else if (val > transitions[mid]) ++ lo = mid + 1; ++ else ++ break; ++ } ++ return transitions[mid]; ++ } ++ ++ /** ++ * Get the time zone offset for the specified date, modified in case of ++ * daylight savings. This is the offset to add to UTC to get the local ++ * time. ++ * @param date the date represented in millisecends ++ * since January 1, 1970 00:00:00 GMT. ++ */ ++ public int getOffset(long date) ++ { ++ long d = (date >= 0 ? date / 1000 : (date + 1) / 1000 - 1); ++ long transition = findTransition(d); ++ ++ // For times on or after last transition use lastRule. ++ if (transition == Long.MAX_VALUE) ++ return lastRule.getOffset(date); ++ ++ return (int) (((transition << OFFSET_SHIFT) >> OFFSET_SHIFT) * 1000); ++ } ++ ++ /** ++ * Returns the time zone offset to GMT in milliseconds, ignoring ++ * day light savings. ++ * @return the time zone offset. ++ */ ++ public int getRawOffset() ++ { ++ return rawOffset; ++ } ++ ++ /** ++ * Sets the standard time zone offset to GMT. ++ * @param rawOffset The time offset from GMT in milliseconds. ++ */ ++ public void setRawOffset(int rawOffset) ++ { ++ this.rawOffset = rawOffset; ++ lastRule.setRawOffset(rawOffset); ++ } ++ ++ private void computeDSTSavings() ++ { ++ if (lastRule.useDaylightTime()) ++ { ++ dstSavings = lastRule.getDSTSavings(); ++ useDaylight = true; ++ } ++ else ++ { ++ dstSavings = 0; ++ useDaylight = false; ++ // lastRule might say no DST is in effect simply because ++ // the DST rules are too complex for SimpleTimeZone, say ++ // for Asia/Jerusalem. ++ // Look at the last DST offset if it is newer than current time. ++ long currentSecs = System.currentTimeMillis() / 1000; ++ int i; ++ for (i = transitions.length - 1; ++ i >= 0 && currentSecs < (transitions[i] >> SECS_SHIFT); ++ i--) ++ if ((transitions[i] & IS_DST) != 0) ++ { ++ dstSavings = (int) (((transitions[i] << OFFSET_SHIFT) ++ >> OFFSET_SHIFT) * 1000) ++ - rawOffset; ++ useDaylight = true; ++ break; ++ } ++ } ++ } ++ ++ /** ++ * Gets the daylight savings offset. This is a positive offset in ++ * milliseconds with respect to standard time. Typically this ++ * is one hour, but for some time zones this may be half an our. ++ * @return the daylight savings offset in milliseconds. ++ */ ++ public int getDSTSavings() ++ { ++ return dstSavings; ++ } ++ ++ /** ++ * Returns if this time zone uses daylight savings time. ++ * @return true, if we use daylight savings time, false otherwise. ++ */ ++ public boolean useDaylightTime() ++ { ++ return useDaylight; ++ } ++ ++ /** ++ * Determines if the given date is in daylight savings time. ++ * @return true, if it is in daylight savings time, false otherwise. ++ */ ++ public boolean inDaylightTime(Date date) ++ { ++ long d = date.getTime(); ++ d = (d >= 0 ? d / 1000 : (d + 1) / 1000 - 1); ++ long transition = findTransition(d); ++ ++ // For times on or after last transition use lastRule. ++ if (transition == Long.MAX_VALUE) ++ return lastRule.inDaylightTime(date); ++ ++ return (transition & IS_DST) != 0; ++ } ++ ++ /** ++ * Generates the hashCode for the SimpleDateFormat object. It is ++ * the rawOffset, possibly, if useDaylightSavings is true, xored ++ * with startYear, startMonth, startDayOfWeekInMonth, ..., endTime. ++ */ ++ public synchronized int hashCode() ++ { ++ int hash = lastRule.hashCode(); ++ // FIXME - hash transitions? ++ return hash; ++ } ++ ++ public synchronized boolean equals(Object o) ++ { ++ if (! hasSameRules((TimeZone) o)) ++ return false; ++ ++ ZoneInfo zone = (ZoneInfo) o; ++ return getID().equals(zone.getID()); ++ } ++ ++ /** ++ * Test if the other time zone uses the same rule and only ++ * possibly differs in ID. This implementation for this particular ++ * class will return true if the other object is a ZoneInfo, ++ * the raw offsets and useDaylight are identical and if useDaylight ++ * is true, also the start and end datas are identical. ++ * @return true if this zone uses the same rule. ++ */ ++ public boolean hasSameRules(TimeZone o) ++ { ++ if (this == o) ++ return true; ++ if (! (o instanceof ZoneInfo)) ++ return false; ++ ZoneInfo zone = (ZoneInfo) o; ++ if (zone.hashCode() != hashCode() || rawOffset != zone.rawOffset) ++ return false; ++ if (! lastRule.equals(zone.lastRule)) ++ return false; ++ // FIXME - compare transitions? ++ return true; ++ } ++ ++ /** ++ * Returns a string representation of this ZoneInfo object. ++ * @return a string representation of this ZoneInfo object. ++ */ ++ public String toString() ++ { ++ return getClass().getName() + "[" + "id=" + getID() + ",offset=" ++ + rawOffset + ",transitions=" + transitions.length ++ + ",useDaylight=" + useDaylight ++ + (useDaylight ? (",dstSavings=" + dstSavings) : "") ++ + ",lastRule=" + lastRule.toString() + "]"; ++ } ++ ++ /** ++ * Reads zic(8) compiled timezone data file from file ++ * and returns a TimeZone class describing it, either ++ * SimpleTimeZone or ZoneInfo depending on whether ++ * it can be described by SimpleTimeZone rule or not. ++ */ ++ public static TimeZone readTZFile(String id, String file) ++ { ++ DataInputStream dis = null; ++ try ++ { ++ FileInputStream fis = new FileInputStream(file); ++ BufferedInputStream bis = new BufferedInputStream(fis); ++ dis = new DataInputStream(bis); ++ ++ // Make sure we are reading a tzfile. ++ byte[] tzif = new byte[5]; ++ dis.readFully(tzif); ++ int tzif2 = 4; ++ if (tzif[0] == 'T' && tzif[1] == 'Z' ++ && tzif[2] == 'i' && tzif[3] == 'f') ++ { ++ if (tzif[4] >= '2') ++ tzif2 = 8; ++ // Reserved bytes ++ skipFully(dis, 16 - 1); ++ } ++ else ++ // Darwin has tzdata files that don't start with the TZif marker ++ skipFully(dis, 16 - 5); ++ ++ int ttisgmtcnt = dis.readInt(); ++ int ttisstdcnt = dis.readInt(); ++ int leapcnt = dis.readInt(); ++ int timecnt = dis.readInt(); ++ int typecnt = dis.readInt(); ++ int charcnt = dis.readInt(); ++ if (tzif2 == 8) ++ { ++ skipFully(dis, timecnt * (4 + 1) + typecnt * (4 + 1 + 1) + charcnt ++ + leapcnt * (4 + 4) + ttisgmtcnt + ttisstdcnt); ++ ++ dis.readFully(tzif); ++ if (tzif[0] != 'T' || tzif[1] != 'Z' || tzif[2] != 'i' ++ || tzif[3] != 'f' || tzif[4] < '2') ++ return null; ++ ++ // Reserved bytes ++ skipFully(dis, 16 - 1); ++ ttisgmtcnt = dis.readInt(); ++ ttisstdcnt = dis.readInt(); ++ leapcnt = dis.readInt(); ++ timecnt = dis.readInt(); ++ typecnt = dis.readInt(); ++ charcnt = dis.readInt(); ++ } ++ ++ // Sanity checks ++ if (typecnt <= 0 || timecnt < 0 || charcnt < 0 ++ || leapcnt < 0 || ttisgmtcnt < 0 || ttisstdcnt < 0 ++ || ttisgmtcnt > typecnt || ttisstdcnt > typecnt) ++ return null; ++ ++ // Transition times ++ long[] times = new long[timecnt]; ++ for (int i = 0; i < timecnt; i++) ++ if (tzif2 == 8) ++ times[i] = dis.readLong(); ++ else ++ times[i] = (long) dis.readInt(); ++ ++ // Transition types ++ int[] types = new int[timecnt]; ++ for (int i = 0; i < timecnt; i++) ++ { ++ types[i] = dis.readByte(); ++ if (types[i] < 0) ++ types[i] += 256; ++ if (types[i] >= typecnt) ++ return null; ++ } ++ ++ // Types ++ int[] offsets = new int[typecnt]; ++ int[] typeflags = new int[typecnt]; ++ for (int i = 0; i < typecnt; i++) ++ { ++ offsets[i] = dis.readInt(); ++ if (offsets[i] >= IS_DST / 2 || offsets[i] <= -IS_DST / 2) ++ return null; ++ int dst = dis.readByte(); ++ int abbrind = dis.readByte(); ++ if (abbrind < 0) ++ abbrind += 256; ++ if (abbrind >= charcnt) ++ return null; ++ typeflags[i] = (dst != 0 ? (1 << 8) : 0) + abbrind; ++ } ++ ++ // Abbrev names ++ byte[] names = new byte[charcnt]; ++ dis.readFully(names); ++ ++ // Leap transitions, for now ignore ++ skipFully(dis, leapcnt * (tzif2 + 4) + ttisstdcnt + ttisgmtcnt); ++ ++ // tzIf2 format has optional POSIX TZ env string ++ String tzstr = null; ++ if (tzif2 == 8 && dis.readByte() == '\n') ++ { ++ tzstr = dis.readLine(); ++ if (tzstr.length() <= 0) ++ tzstr = null; ++ } ++ ++ // Get std/dst_offset and dst/non-dst time zone names. ++ int std_ind = -1; ++ int dst_ind = -1; ++ if (timecnt == 0) ++ std_ind = 0; ++ else ++ for (int i = timecnt - 1; i >= 0; i--) ++ { ++ if (std_ind == -1 && (typeflags[types[i]] & (1 << 8)) == 0) ++ std_ind = types[i]; ++ else if (dst_ind == -1 && (typeflags[types[i]] & (1 << 8)) != 0) ++ dst_ind = types[i]; ++ if (dst_ind != -1 && std_ind != -1) ++ break; ++ } ++ ++ if (std_ind == -1) ++ return null; ++ ++ int j = typeflags[std_ind] & 255; ++ while (j < charcnt && names[j] != 0) ++ j++; ++ String std_zonename = new String(names, typeflags[std_ind] & 255, ++ j - (typeflags[std_ind] & 255), ++ "ASCII"); ++ ++ String dst_zonename = ""; ++ if (dst_ind != -1) ++ { ++ j = typeflags[dst_ind] & 255; ++ while (j < charcnt && names[j] != 0) ++ j++; ++ dst_zonename = new String(names, typeflags[dst_ind] & 255, ++ j - (typeflags[dst_ind] & 255), "ASCII"); ++ } ++ ++ // Only use gmt offset when necessary. ++ // Also special case GMT+/- timezones. ++ String std_offset_string = ""; ++ String dst_offset_string = ""; ++ if (tzstr == null ++ && (dst_ind != -1 ++ || (offsets[std_ind] != 0 ++ && !std_zonename.startsWith("GMT+") ++ && !std_zonename.startsWith("GMT-")))) ++ { ++ std_offset_string = Integer.toString(-offsets[std_ind] / 3600); ++ int seconds = -offsets[std_ind] % 3600; ++ if (seconds != 0) ++ { ++ if (seconds < 0) ++ seconds *= -1; ++ if (seconds < 600) ++ std_offset_string += ":0" + Integer.toString(seconds / 60); ++ else ++ std_offset_string += ":" + Integer.toString(seconds / 60); ++ seconds = seconds % 60; ++ if (seconds >= 10) ++ std_offset_string += ":" + Integer.toString(seconds); ++ else if (seconds > 0) ++ std_offset_string += ":0" + Integer.toString(seconds); ++ } ++ ++ if (dst_ind != -1 && offsets[dst_ind] != offsets[std_ind] + 3600) ++ { ++ dst_offset_string = Integer.toString(-offsets[dst_ind] / 3600); ++ seconds = -offsets[dst_ind] % 3600; ++ if (seconds != 0) ++ { ++ if (seconds < 0) ++ seconds *= -1; ++ if (seconds < 600) ++ dst_offset_string ++ += ":0" + Integer.toString(seconds / 60); ++ else ++ dst_offset_string ++ += ":" + Integer.toString(seconds / 60); ++ seconds = seconds % 60; ++ if (seconds >= 10) ++ dst_offset_string += ":" + Integer.toString(seconds); ++ else if (seconds > 0) ++ dst_offset_string += ":0" + Integer.toString(seconds); ++ } ++ } ++ } ++ ++ /* ++ * If no tzIf2 POSIX TZ string is available and the timezone ++ * uses DST, try to guess the last rule by trying to make ++ * sense from transitions at 5 years in the future and onwards. ++ * tzdata actually uses only 3 forms of rules: ++ * fixed date within a month, e.g. change on April, 5th ++ * 1st weekday on or after Nth: change on Sun>=15 in April ++ * last weekday in a month: change on lastSun in April ++ */ ++ String[] change_spec = { null, null }; ++ if (tzstr == null && dst_ind != -1 && timecnt > 10) ++ { ++ long nowPlus5y = System.currentTimeMillis() / 1000 ++ + 5 * 365 * 86400; ++ int first; ++ ++ for (first = timecnt - 1; first >= 0; first--) ++ if (times[first] < nowPlus5y ++ || (types[first] != std_ind && types[first] != dst_ind) ++ || types[first] != types[timecnt - 2 + ((first ^ timecnt) & 1)]) ++ break; ++ first++; ++ ++ if (timecnt - first >= 10 && types[timecnt - 1] != types[timecnt - 2]) ++ { ++ GregorianCalendar cal ++ = new GregorianCalendar(new SimpleTimeZone(0, "GMT")); ++ ++ int[] values = new int[2 * 11]; ++ int i; ++ for (i = timecnt - 1; i >= first; i--) ++ { ++ int base = (i % 2) * 11; ++ int offset = offsets[types[i > first ? i - 1 : i + 1]]; ++ cal.setTimeInMillis((times[i] + offset) * 1000); ++ if (i >= timecnt - 2) ++ { ++ values[base + 0] = cal.get(Calendar.YEAR); ++ values[base + 1] = cal.get(Calendar.MONTH); ++ values[base + 2] = cal.get(Calendar.DAY_OF_MONTH); ++ values[base + 3] ++ = cal.getActualMaximum(Calendar.DAY_OF_MONTH); ++ values[base + 4] = cal.get(Calendar.DAY_OF_WEEK); ++ values[base + 5] = cal.get(Calendar.HOUR_OF_DAY); ++ values[base + 6] = cal.get(Calendar.MINUTE); ++ values[base + 7] = cal.get(Calendar.SECOND); ++ values[base + 8] = values[base + 2]; // Range start ++ values[base + 9] = values[base + 2]; // Range end ++ values[base + 10] = 0; // Determined type ++ } ++ else ++ { ++ int year = cal.get(Calendar.YEAR); ++ int month = cal.get(Calendar.MONTH); ++ int day_of_month = cal.get(Calendar.DAY_OF_MONTH); ++ int month_days ++ = cal.getActualMaximum(Calendar.DAY_OF_MONTH); ++ int day_of_week = cal.get(Calendar.DAY_OF_WEEK); ++ int hour = cal.get(Calendar.HOUR_OF_DAY); ++ int minute = cal.get(Calendar.MINUTE); ++ int second = cal.get(Calendar.SECOND); ++ if (year != values[base + 0] - 1 ++ || month != values[base + 1] ++ || hour != values[base + 5] ++ || minute != values[base + 6] ++ || second != values[base + 7]) ++ break; ++ if (day_of_week == values[base + 4]) ++ { ++ // Either a Sun>=8 or lastSun rule. ++ if (day_of_month < values[base + 8]) ++ values[base + 8] = day_of_month; ++ if (day_of_month > values[base + 9]) ++ values[base + 9] = day_of_month; ++ if (values[base + 10] < 0) ++ break; ++ if (values[base + 10] == 0) ++ { ++ values[base + 10] = 1; ++ // If day of month > 28, this is ++ // certainly lastSun rule. ++ if (values[base + 2] > 28) ++ values[base + 2] = 3; ++ // If day of month isn't in the last ++ // week, it can't be lastSun rule. ++ else if (values[base + 2] ++ <= values[base + 3] - 7) ++ values[base + 3] = 2; ++ } ++ if (values[base + 10] == 1) ++ { ++ // If day of month is > 28, this is ++ // certainly lastSun rule. ++ if (day_of_month > 28) ++ values[base + 10] = 3; ++ // If day of month isn't in the last ++ // week, it can't be lastSun rule. ++ else if (day_of_month <= month_days - 7) ++ values[base + 10] = 2; ++ } ++ else if ((values[base + 10] == 2 ++ && day_of_month > 28) ++ || (values[base + 10] == 3 ++ && day_of_month <= month_days - 7)) ++ break; ++ } ++ else ++ { ++ // Must be fixed day in month rule. ++ if (day_of_month != values[base + 2] ++ || values[base + 10] > 0) ++ break; ++ values[base + 4] = day_of_week; ++ values[base + 10] = -1; ++ } ++ values[base + 0] -= 1; ++ } ++ } ++ ++ if (i < first) ++ { ++ for (i = 0; i < 2; i++) ++ { ++ int base = 11 * i; ++ if (values[base + 10] == 0) ++ continue; ++ if (values[base + 10] == -1) ++ { ++ int[] dayCount ++ = { 0, 31, 59, 90, 120, 151, ++ 181, 212, 243, 273, 304, 334 }; ++ int d = dayCount[values[base + 1] ++ - Calendar.JANUARY]; ++ d += values[base + 2]; ++ change_spec[i] = ",J" + Integer.toString(d); ++ } ++ else if (values[base + 10] == 2) ++ { ++ // If we haven't seen all days of the week, ++ // we can't be sure what the rule really is. ++ if (values[base + 8] + 6 != values[base + 9]) ++ continue; ++ ++ int d; ++ d = values[base + 1] - Calendar.JANUARY + 1; ++ // E.g. Sun >= 5 is not representable in POSIX ++ // TZ env string, use ",Am.n.d" extension ++ // where m is month 1 .. 12, n is the date on ++ // or after which it happens and d is day ++ // of the week, 0 .. 6. So Sun >= 5 in April ++ // is ",A4.5.0". ++ if ((values[base + 8] % 7) == 1) ++ { ++ change_spec[i] = ",M" + Integer.toString(d); ++ d = (values[base + 8] + 6) / 7; ++ } ++ else ++ { ++ change_spec[i] = ",A" + Integer.toString(d); ++ d = values[base + 8]; ++ } ++ change_spec[i] += "." + Integer.toString(d); ++ d = values[base + 4] - Calendar.SUNDAY; ++ change_spec[i] += "." + Integer.toString(d); ++ } ++ else ++ { ++ // If we don't know whether this is lastSun or ++ // Sun >= 22 rule. That can be either because ++ // there was insufficient number of ++ // transitions, or February, where it is quite ++ // probable we haven't seen any 29th dates. ++ // For February, assume lastSun rule, otherwise ++ // punt. ++ if (values[base + 10] == 1 ++ && values[base + 1] != Calendar.FEBRUARY) ++ continue; ++ ++ int d; ++ d = values[base + 1] - Calendar.JANUARY + 1; ++ change_spec[i] = ",M" + Integer.toString(d); ++ d = values[base + 4] - Calendar.SUNDAY; ++ change_spec[i] += ".5." + Integer.toString(d); ++ } ++ ++ // Don't add time specification if time is ++ // 02:00:00. ++ if (values[base + 5] != 2 ++ || values[base + 6] != 0 ++ || values[base + 7] != 0) ++ { ++ int d = values[base + 5]; ++ change_spec[i] += "/" + Integer.toString(d); ++ if (values[base + 6] != 0 || values[base + 7] != 0) ++ { ++ d = values[base + 6]; ++ if (d < 10) ++ change_spec[i] ++ += ":0" + Integer.toString(d); ++ else ++ change_spec[i] += ":" + Integer.toString(d); ++ d = values[base + 7]; ++ if (d >= 10) ++ change_spec[i] ++ += ":" + Integer.toString(d); ++ else if (d > 0) ++ change_spec[i] ++ += ":0" + Integer.toString(d); ++ } ++ } ++ } ++ if (types[(timecnt - 1) & -2] == std_ind) ++ { ++ String tmp = change_spec[0]; ++ change_spec[0] = change_spec[1]; ++ change_spec[1] = tmp; ++ } ++ } ++ } ++ } ++ ++ if (tzstr == null) ++ { ++ tzstr = std_zonename + std_offset_string; ++ if (change_spec[0] != null && change_spec[1] != null) ++ tzstr += dst_zonename + dst_offset_string ++ + change_spec[0] + change_spec[1]; ++ } ++ ++ if (timecnt == 0) ++ return new SimpleTimeZone(offsets[std_ind] * 1000, ++ id != null ? id : tzstr); ++ ++ SimpleTimeZone endRule = createLastRule(tzstr); ++ if (endRule == null) ++ return null; ++ ++ /* Finally adjust the times array into the form the constructor ++ * expects. times[0] is special, the offset and DST flag there ++ * are for all times before that transition. Use the first non-DST ++ * type. For all other transitions, the data file has the type ++ * () for the time interval starting ++ */ ++ for (int i = 0; i < typecnt; i++) ++ if ((typeflags[i] & (1 << 8)) == 0) ++ { ++ times[0] = (times[0] << SECS_SHIFT) | (offsets[i] & OFFSET_MASK); ++ break; ++ } ++ ++ for (int i = 1; i < timecnt; i++) ++ times[i] = (times[i] << SECS_SHIFT) ++ | (offsets[types[i - 1]] & OFFSET_MASK) ++ | ((typeflags[types[i - 1]] & (1 << 8)) != 0 ? IS_DST : 0); ++ ++ return new ZoneInfo(offsets[std_ind] * 1000, id != null ? id : tzstr, ++ times, endRule); ++ } ++ catch (IOException ioe) ++ { ++ // Parse error, not a proper tzfile. ++ return null; ++ } ++ finally ++ { ++ try ++ { ++ if (dis != null) ++ dis.close(); ++ } ++ catch(IOException ioe) ++ { ++ // Error while close, nothing we can do. ++ } ++ } ++ } ++ ++ /** ++ * Skips the requested number of bytes in the given InputStream. ++ * Throws EOFException if not enough bytes could be skipped. ++ * Negative numbers of bytes to skip are ignored. ++ */ ++ private static void skipFully(InputStream is, long l) throws IOException ++ { ++ while (l > 0) ++ { ++ long k = is.skip(l); ++ if (k <= 0) ++ throw new EOFException(); ++ l -= k; ++ } ++ } ++ ++ /** ++ * Create a SimpleTimeZone from a POSIX TZ environment string, ++ * see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html ++ * for details. ++ * It supports also an extension, where Am.n.d rule (m 1 .. 12, n 1 .. 25, d ++ * 0 .. 6) describes day of week d on or after nth day of month m. ++ * Say A4.5.0 is Sun>=5 in April. ++ */ ++ private static SimpleTimeZone createLastRule(String tzstr) ++ { ++ String stdName = null; ++ int stdOffs; ++ int dstOffs; ++ try ++ { ++ int idLength = tzstr.length(); ++ ++ int index = 0; ++ int prevIndex; ++ char c; ++ ++ // get std ++ do ++ c = tzstr.charAt(index); ++ while (c != '+' && c != '-' && c != ',' && c != ':' ++ && ! Character.isDigit(c) && c != '\0' && ++index < idLength); ++ ++ if (index >= idLength) ++ return new SimpleTimeZone(0, tzstr); ++ ++ stdName = tzstr.substring(0, index); ++ prevIndex = index; ++ ++ // get the std offset ++ do ++ c = tzstr.charAt(index++); ++ while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c)) ++ && index < idLength); ++ if (index < idLength) ++ index--; ++ ++ { // convert the dst string to a millis number ++ String offset = tzstr.substring(prevIndex, index); ++ prevIndex = index; ++ ++ if (offset.charAt(0) == '+' || offset.charAt(0) == '-') ++ stdOffs = parseTime(offset.substring(1)); ++ else ++ stdOffs = parseTime(offset); ++ ++ if (offset.charAt(0) == '-') ++ stdOffs = -stdOffs; ++ ++ // TZ timezone offsets are positive when WEST of the meridian. ++ stdOffs = -stdOffs; ++ } ++ ++ // Done yet? (Format: std offset) ++ if (index >= idLength) ++ return new SimpleTimeZone(stdOffs, stdName); ++ ++ // get dst ++ do ++ c = tzstr.charAt(index); ++ while (c != '+' && c != '-' && c != ',' && c != ':' ++ && ! Character.isDigit(c) && c != '\0' && ++index < idLength); ++ ++ // Done yet? (Format: std offset dst) ++ if (index >= idLength) ++ return new SimpleTimeZone(stdOffs, stdName); ++ ++ // get the dst offset ++ prevIndex = index; ++ do ++ c = tzstr.charAt(index++); ++ while ((c == '-' || c == '+' || c == ':' || Character.isDigit(c)) ++ && index < idLength); ++ if (index < idLength) ++ index--; ++ ++ if (index == prevIndex && (c == ',' || c == ';')) ++ { ++ // Missing dst offset defaults to one hour ahead of standard ++ // time. ++ dstOffs = stdOffs + 60 * 60 * 1000; ++ } ++ else ++ { // convert the dst string to a millis number ++ String offset = tzstr.substring(prevIndex, index); ++ prevIndex = index; ++ ++ if (offset.charAt(0) == '+' || offset.charAt(0) == '-') ++ dstOffs = parseTime(offset.substring(1)); ++ else ++ dstOffs = parseTime(offset); ++ ++ if (offset.charAt(0) == '-') ++ dstOffs = -dstOffs; ++ ++ // TZ timezone offsets are positive when WEST of the meridian. ++ dstOffs = -dstOffs; ++ } ++ ++ // Done yet? (Format: std offset dst offset) ++ if (index >= idLength) ++ return new SimpleTimeZone(stdOffs, stdName); ++ ++ // get the DST rule ++ if (tzstr.charAt(index) == ',' ++ || tzstr.charAt(index) == ';') ++ { ++ index++; ++ int offs = index; ++ while (tzstr.charAt(index) != ',' ++ && tzstr.charAt(index) != ';') ++ index++; ++ String startTime = tzstr.substring(offs, index); ++ index++; ++ String endTime = tzstr.substring(index); ++ ++ index = startTime.indexOf('/'); ++ int startMillis; ++ int endMillis; ++ String startDate; ++ String endDate; ++ if (index != -1) ++ { ++ startDate = startTime.substring(0, index); ++ startMillis = parseTime(startTime.substring(index + 1)); ++ } ++ else ++ { ++ startDate = startTime; ++ // if time isn't given, default to 2:00:00 AM. ++ startMillis = 2 * 60 * 60 * 1000; ++ } ++ index = endTime.indexOf('/'); ++ if (index != -1) ++ { ++ endDate = endTime.substring(0, index); ++ endMillis = parseTime(endTime.substring(index + 1)); ++ } ++ else ++ { ++ endDate = endTime; ++ // if time isn't given, default to 2:00:00 AM. ++ endMillis = 2 * 60 * 60 * 1000; ++ } ++ ++ int[] start = getDateParams(startDate); ++ int[] end = getDateParams(endDate); ++ return new SimpleTimeZone(stdOffs, tzstr, start[0], start[1], ++ start[2], startMillis, end[0], end[1], ++ end[2], endMillis, (dstOffs - stdOffs)); ++ } ++ } ++ ++ catch (IndexOutOfBoundsException _) ++ { ++ } ++ catch (NumberFormatException _) ++ { ++ } ++ ++ return null; ++ } ++ ++ /** ++ * Parses and returns the params for a POSIX TZ date field, ++ * in the format int[]{ month, day, dayOfWeek }, following the ++ * SimpleTimeZone constructor rules. ++ */ ++ private static int[] getDateParams(String date) ++ { ++ int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; ++ int month; ++ int type = 0; ++ ++ if (date.charAt(0) == 'M' || date.charAt(0) == 'm') ++ type = 1; ++ else if (date.charAt(0) == 'A' || date.charAt(0) == 'a') ++ type = 2; ++ ++ if (type > 0) ++ { ++ int day; ++ ++ // Month, week of month, day of week ++ // "Mm.w.d". d is between 0 (Sunday) and 6. Week w is ++ // between 1 and 5; Week 1 is the first week in which day d ++ // occurs and Week 5 specifies the last d day in the month. ++ // Month m is between 1 and 12. ++ ++ // Month, day of month, day of week ++ // ZoneInfo extension, not in POSIX ++ // "Am.n.d". d is between 0 (Sunday) and 6. Day of month n is ++ // between 1 and 25. Month m is between 1 and 12. ++ ++ month = Integer.parseInt(date.substring(1, date.indexOf('.'))); ++ int week = Integer.parseInt(date.substring(date.indexOf('.') + 1, ++ date.lastIndexOf('.'))); ++ int dayOfWeek = Integer.parseInt(date.substring(date.lastIndexOf('.') ++ + 1)); ++ dayOfWeek++; // Java day of week is one-based, Sunday is first day. ++ ++ if (type == 2) ++ { ++ day = week; ++ dayOfWeek = -dayOfWeek; ++ } ++ else if (week == 5) ++ day = -1; // last day of month is -1 in java, 5 in TZ ++ else ++ { ++ // First day of week starting on or after. For example, ++ // to specify the second Sunday of April, set month to ++ // APRIL, day-of-month to 8, and day-of-week to -SUNDAY. ++ day = (week - 1) * 7 + 1; ++ dayOfWeek = -dayOfWeek; ++ } ++ ++ month--; // Java month is zero-based. ++ return new int[] { month, day, dayOfWeek }; ++ } ++ ++ // julian day, either zero-based 0<=n<=365 (incl feb 29) ++ // or one-based 1<=n<=365 (no feb 29) ++ int julianDay; // Julian day ++ ++ if (date.charAt(0) != 'J' || date.charAt(0) != 'j') ++ { ++ julianDay = Integer.parseInt(date.substring(1)); ++ julianDay++; // make 1-based ++ // Adjust day count to include feb 29. ++ dayCount = new int[] ++ { ++ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 ++ }; ++ } ++ else ++ // 1-based julian day ++ julianDay = Integer.parseInt(date); ++ ++ int i = 11; ++ while (i > 0) ++ if (dayCount[i] < julianDay) ++ break; ++ else ++ i--; ++ julianDay -= dayCount[i]; ++ month = i; ++ return new int[] { month, julianDay, 0 }; ++ } ++ ++ /** ++ * Parses a time field hh[:mm[:ss]], returning the result ++ * in milliseconds. No leading sign. ++ */ ++ private static int parseTime(String time) ++ { ++ int millis = 0; ++ int i = 0; ++ ++ while (i < time.length()) ++ if (time.charAt(i) == ':') ++ break; ++ else ++ i++; ++ millis = 60 * 60 * 1000 * Integer.parseInt(time.substring(0, i)); ++ if (i >= time.length()) ++ return millis; ++ ++ int iprev = ++i; ++ while (i < time.length()) ++ if (time.charAt(i) == ':') ++ break; ++ else ++ i++; ++ millis += 60 * 1000 * Integer.parseInt(time.substring(iprev, i)); ++ if (i >= time.length()) ++ return millis; ++ ++ millis += 1000 * Integer.parseInt(time.substring(++i)); ++ return millis; ++ } ++} diff --git a/SOURCES/gcc34-ldbl-hack.patch b/SOURCES/gcc34-ldbl-hack.patch new file mode 100644 index 0000000..0c0c7ac --- /dev/null +++ b/SOURCES/gcc34-ldbl-hack.patch @@ -0,0 +1,54 @@ +--- libstdc++-v3/libmath/stubs.c.jj 2005-11-21 08:43:21.000000000 -0500 ++++ libstdc++-v3/libmath/stubs.c 2006-08-23 03:30:53.000000000 -0400 +@@ -27,9 +27,38 @@ + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. */ + ++#if defined __s390__ || defined __powerpc__ ++/* Lie. */ ++#define __LONG_DOUBLE_128__ 1 ++#endif ++ + #include + #include "config.h" + ++#if defined __s390__ || defined __powerpc__ ++#undef HAVE_ACOSL ++#undef HAVE_ASINL ++#undef HAVE_ATAN2L ++#undef HAVE_ATANL ++#undef HAVE_CEILL ++#undef HAVE_COSHL ++#undef HAVE_COSL ++#undef HAVE_EXPL ++#undef HAVE_FLOORL ++#undef HAVE_FMODL ++#undef HAVE_FREXPL ++#undef HAVE_LDEXPL ++#undef HAVE_LOG10L ++#undef HAVE_LOGL ++#undef HAVE_MODFL ++#undef HAVE_POWL ++#undef HAVE_SINHL ++#undef HAVE_SINL ++#undef HAVE_SQRTL ++#undef HAVE_TANHL ++#undef HAVE_TANL ++#endif ++ + /* For targets which do not have support for long double versions, + we use the crude approximation. We'll do better later. */ + +@@ -273,6 +302,12 @@ hypotl(long double x, long double y) + x /= s; y /= s; + return s * sqrtl(x * x + y * y); + } ++#elif (defined __s390__ || defined __powerpc__) && defined HAVE_HYPOT ++long double ++hypotl(long double x, long double y) ++{ ++ return hypot((double) x, (double) y); ++} + #endif + + diff --git a/SOURCES/gcc34-libgcc-additions.patch b/SOURCES/gcc34-libgcc-additions.patch new file mode 100644 index 0000000..1adb0a3 --- /dev/null +++ b/SOURCES/gcc34-libgcc-additions.patch @@ -0,0 +1,543 @@ +2007-01-05 Jakub Jelinek + + PR c/30360 + * libgcc2.c (__divdc3): Compare c and d against 0.0 instead of + denom against 0.0. + +2005-11-22 Joseph S. Myers + + * libgcc-std.ver (GCC_4.2.0): New version. + * libgcc2.c (__floatundixf, __floatunditf, __floatundidf, + __floatundisf): New functions. + * libgcc2.h (__floatundixf, __floatunditf, __floatundidf, + __floatundisf): Declare. + * mklibgcc.in (lib2funcs): Add _floatundidf, _floatundisf, + _floatundixf, and _floatunditf. + +2005-03-30 Fariborz Jahanian + + * libgcc2.h (__powisf2, __powidf2, __powixf2, __powitf2): Change + 2nd argument type to int. + * libgcc2.c: Change prototype of __powi* functions to use + int. + +2005-02-11 Richard Henderson + + * libgcc2.c (__divsc3, __divdc3, __divxc3, __divtc3, + __mulsc3, __muldc3, __mulxc3, __multc3): New. + * libgcc2.h: Declare them. + * libgcc-std.ver: Export them. + * mklibgcc.in (lib2funcs): Build them. + +2005-02-09 Richard Guenther + + PR middle-end/19402 + * libgcc2.h: Add prototypes for __builtin_powi[lf]. + * libgcc2.c: Add __builtin_powi[lf] implementation. + * mklibgcc.in: Add __builtin_powi[lf] to lib2funcs. + +--- gcc/libgcc-std.ver.jj 2007-03-02 09:27:16.000000000 +0100 ++++ gcc/libgcc-std.ver 2007-03-02 10:32:27.000000000 +0100 +@@ -235,7 +235,39 @@ GCC_3.4.4 { + __subvti3 + } + +-%inherit GCC_4.2.0 GCC_3.4.4 ++%inherit GCC_4.0.0 GCC_3.4.4 ++GCC_4.0.0 { ++ # libgcc2 __builtin_powi helpers. ++ __powisf2 ++ __powidf2 ++ __powixf2 ++ __powitf2 ++ ++ # c99 compliant complex arithmetic ++ __divsc3 ++ __divdc3 ++ __divxc3 ++ __divtc3 ++ __mulsc3 ++ __muldc3 ++ __mulxc3 ++ __multc3 ++} ++ ++%inherit GCC_4.2.0 GCC_4.0.0 + GCC_4.2.0 { ++ # unsigned-to-floating conversions ++ __floatunsisf ++ __floatunsidf ++ __floatunsixf ++ __floatunsitf ++ __floatundidf ++ __floatundisf ++ __floatundixf ++ __floatunditf ++ __floatuntidf ++ __floatuntisf ++ __floatuntixf ++ __floatuntitf + _Unwind_GetIPInfo + } +--- gcc/libgcc2.h.jj 2006-10-05 00:37:01.000000000 +0200 ++++ gcc/libgcc2.h 2007-03-02 11:26:31.000000000 +0100 +@@ -88,12 +88,16 @@ typedef unsigned int UTItype __attribute + + typedef float SFtype __attribute__ ((mode (SF))); + typedef float DFtype __attribute__ ((mode (DF))); ++typedef _Complex float SCtype; ++typedef _Complex double DCtype; + + #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 + typedef float XFtype __attribute__ ((mode (XF))); ++typedef _Complex long double XCtype; + #endif + #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 + typedef float TFtype __attribute__ ((mode (TF))); ++typedef _Complex long double TCtype; + #endif + + #else /* BITS_PER_UNIT != 8 */ +@@ -216,6 +220,10 @@ typedef int word_type __attribute__ ((mo + #define __floatditf __NDW(float,tf) + #define __floatdidf __NDW(float,df) + #define __floatdisf __NDW(float,sf) ++#define __floatundixf __NDW(floatun,xf) ++#define __floatunditf __NDW(floatun,tf) ++#define __floatundidf __NDW(floatun,df) ++#define __floatundisf __NDW(floatun,sf) + #define __fixunsxfSI __NW(fixunsxf,) + #define __fixunstfSI __NW(fixunstf,) + #define __fixunsdfSI __NW(fixunsdf,) +@@ -293,27 +301,47 @@ extern SItype __negvsi2 (SItype); + #endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ + + #if BITS_PER_UNIT == 8 ++#undef int + extern DWtype __fixdfdi (DFtype); + extern DWtype __fixsfdi (SFtype); + extern DFtype __floatdidf (DWtype); + extern SFtype __floatdisf (DWtype); ++extern DFtype __floatundidf (UDWtype); ++extern SFtype __floatundisf (UDWtype); + extern UWtype __fixunsdfSI (DFtype); + extern UWtype __fixunssfSI (SFtype); + extern DWtype __fixunsdfDI (DFtype); + extern DWtype __fixunssfDI (SFtype); ++extern SFtype __powisf2 (SFtype, int); ++extern DFtype __powidf2 (DFtype, int); ++ ++extern SCtype __divsc3 (SFtype, SFtype, SFtype, SFtype); ++extern SCtype __mulsc3 (SFtype, SFtype, SFtype, SFtype); ++extern DCtype __divdc3 (DFtype, DFtype, DFtype, DFtype); ++extern DCtype __muldc3 (DFtype, DFtype, DFtype, DFtype); + + #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 + extern DWtype __fixxfdi (XFtype); + extern DWtype __fixunsxfDI (XFtype); + extern XFtype __floatdixf (DWtype); ++extern XFtype __floatundixf (UDWtype); + extern UWtype __fixunsxfSI (XFtype); ++extern XFtype __powixf2 (XFtype, int); ++extern XCtype __divxc3 (XFtype, XFtype, XFtype, XFtype); ++extern XCtype __mulxc3 (XFtype, XFtype, XFtype, XFtype); + #endif + + #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 + extern DWtype __fixunstfDI (TFtype); + extern DWtype __fixtfdi (TFtype); + extern TFtype __floatditf (DWtype); ++extern TFtype __floatunditf (UDWtype); ++extern TFtype __powitf2 (TFtype, int); ++extern TCtype __divtc3 (TFtype, TFtype, TFtype, TFtype); ++extern TCtype __multc3 (TFtype, TFtype, TFtype, TFtype); + #endif ++ ++#define int bogus_type + #endif /* BITS_PER_UNIT == 8 */ + + /* DWstructs are pairs of Wtype values in the order determined by +--- gcc/mklibgcc.in.jj 2006-10-05 00:37:01.000000000 +0200 ++++ gcc/mklibgcc.in 2007-03-02 10:31:58.000000000 +0100 +@@ -58,7 +58,9 @@ lib2funcs='_muldi3 _negdi2 _lshrdi3 _ash + _enable_execute_stack _trampoline __main _absvsi2 _absvdi2 _addvsi3 + _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors + _ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab +- _popcountsi2 _popcountdi2 _paritysi2 _paritydi2' ++ _popcountsi2 _popcountdi2 _paritysi2 _paritydi2 _powisf2 _powidf2 ++ _powixf2 _powitf2 _mulsc3 _muldc3 _mulxc3 _multc3 _divsc3 _divdc3 ++ _divxc3 _divtc3 _floatundidf _floatundisf _floatundixf _floatunditf' + + # Disable SHLIB_LINK if shared libgcc not enabled. + if [ "@enable_shared@" = "no" ]; then +--- gcc/libgcc2.c.jj 2006-10-05 00:37:01.000000000 +0200 ++++ gcc/libgcc2.c 2007-03-02 10:58:07.000000000 +0100 +@@ -1331,6 +1331,23 @@ __floatdixf (DWtype u) + } + #endif + ++#if defined(L_floatundixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) ++#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) ++#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) ++#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) ++ ++XFtype ++__floatundixf (UDWtype u) ++{ ++ XFtype d = (UWtype) (u >> WORD_SIZE); ++ d *= HIGH_HALFWORD_COEFF; ++ d *= HIGH_HALFWORD_COEFF; ++ d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); ++ ++ return d; ++} ++#endif ++ + #if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) + #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) + #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) +@@ -1348,6 +1365,23 @@ __floatditf (DWtype u) + } + #endif + ++#if defined(L_floatunditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) ++#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) ++#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) ++#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) ++ ++TFtype ++__floatunditf (UDWtype u) ++{ ++ TFtype d = (UWtype) (u >> WORD_SIZE); ++ d *= HIGH_HALFWORD_COEFF; ++ d *= HIGH_HALFWORD_COEFF; ++ d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); ++ ++ return d; ++} ++#endif ++ + #ifdef L_floatdidf + #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) + #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) +@@ -1365,6 +1399,23 @@ __floatdidf (DWtype u) + } + #endif + ++#ifdef L_floatundidf ++#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) ++#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) ++#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) ++ ++DFtype ++__floatundidf (UDWtype u) ++{ ++ DFtype d = (UWtype) (u >> WORD_SIZE); ++ d *= HIGH_HALFWORD_COEFF; ++ d *= HIGH_HALFWORD_COEFF; ++ d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); ++ ++ return d; ++} ++#endif ++ + #ifdef L_floatdisf + #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) + #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) +@@ -1409,6 +1460,49 @@ __floatdisf (DWtype u) + } + #endif + ++#ifdef L_floatundisf ++#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) ++#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) ++#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) ++ ++#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT) ++#define DF_SIZE DBL_MANT_DIG ++#define SF_SIZE FLT_MANT_DIG ++ ++SFtype ++__floatundisf (UDWtype u) ++{ ++ /* Protect against double-rounding error. ++ Represent any low-order bits, that might be truncated in DFmode, ++ by a bit that won't be lost. The bit can go in anywhere below the ++ rounding position of the SFmode. A fixed mask and bit position ++ handles all usual configurations. It doesn't handle the case ++ of 128-bit DImode, however. */ ++ if (DF_SIZE < DI_SIZE ++ && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE)) ++ { ++#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE)) ++ if (u >= ((UDWtype) 1 << DF_SIZE)) ++ { ++ if ((UDWtype) u & (REP_BIT - 1)) ++ { ++ u &= ~ (REP_BIT - 1); ++ u |= REP_BIT; ++ } ++ } ++ } ++ /* Do the calculation in DFmode ++ so that we don't lose any of the precision of the high word ++ while multiplying it. */ ++ DFtype f = (UWtype) (u >> WORD_SIZE); ++ f *= HIGH_HALFWORD_COEFF; ++ f *= HIGH_HALFWORD_COEFF; ++ f += (UWtype) (u & (HIGH_WORD_COEFF - 1)); ++ ++ return (SFtype) f; ++} ++#endif ++ + #if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 + /* Reenable the normal types, in case limits.h needs them. */ + #undef char +@@ -1475,6 +1569,246 @@ __fixunssfSI (SFtype a) + } + #endif + ++/* Integer power helper used from __builtin_powi for non-constant ++ exponents. */ ++ ++#if defined(L_powisf2) || defined(L_powidf2) \ ++ || (defined(L_powixf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) \ ++ || (defined(L_powitf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) ++# if defined(L_powisf2) ++# define TYPE SFtype ++# define NAME __powisf2 ++# elif defined(L_powidf2) ++# define TYPE DFtype ++# define NAME __powidf2 ++# elif defined(L_powixf2) ++# define TYPE XFtype ++# define NAME __powixf2 ++# elif defined(L_powitf2) ++# define TYPE TFtype ++# define NAME __powitf2 ++# endif ++ ++#undef int ++#undef unsigned ++TYPE ++NAME (TYPE x, int m) ++{ ++ unsigned int n = m < 0 ? -m : m; ++ TYPE y = n % 2 ? x : 1; ++ while (n >>= 1) ++ { ++ x = x * x; ++ if (n % 2) ++ y = y * x; ++ } ++ return m < 0 ? 1/y : y; ++} ++ ++#endif ++ ++#if defined(L_mulsc3) || defined(L_divsc3) \ ++ || defined(L_muldc3) || defined(L_divdc3) \ ++ || (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 \ ++ && (defined(L_mulxc3) || defined(L_divxc3))) \ ++ || (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 \ ++ && (defined(L_multc3) || defined(L_divtc3))) ++ ++#undef float ++#undef double ++#undef long ++ ++#if defined(L_mulsc3) || defined(L_divsc3) ++# define MTYPE SFtype ++# define CTYPE SCtype ++# define MODE sc ++# define CEXT f ++# define NOTRUNC __FLT_EVAL_METHOD__ == 0 ++#elif defined(L_muldc3) || defined(L_divdc3) ++# define MTYPE DFtype ++# define CTYPE DCtype ++# define MODE dc ++# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64 ++# define CEXT l ++# define NOTRUNC 1 ++# else ++# define CEXT ++# define NOTRUNC __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1 ++# endif ++#elif defined(L_mulxc3) || defined(L_divxc3) ++# define MTYPE XFtype ++# define CTYPE XCtype ++# define MODE xc ++# define CEXT l ++# define NOTRUNC 1 ++#elif defined(L_multc3) || defined(L_divtc3) ++# define MTYPE TFtype ++# define CTYPE TCtype ++# define MODE tc ++# define CEXT l ++# define NOTRUNC 1 ++#else ++# error ++#endif ++ ++#define CONCAT3(A,B,C) _CONCAT3(A,B,C) ++#define _CONCAT3(A,B,C) A##B##C ++ ++#define CONCAT2(A,B) _CONCAT2(A,B) ++#define _CONCAT2(A,B) A##B ++ ++/* All of these would be present in a full C99 implementation of ++ and . Our problem is that only a few systems have such full ++ implementations. Further, libgcc_s.so isn't currently linked against ++ libm.so, and even for systems that do provide full C99, the extra overhead ++ of all programs using libgcc having to link against libm. So avoid it. */ ++ ++#define isnan(x) __builtin_expect ((x) != (x), 0) ++#define isfinite(x) __builtin_expect (!isnan((x) - (x)), 1) ++#define isinf(x) __builtin_expect (!isnan(x) & !isfinite(x), 0) ++ ++#define INFINITY CONCAT2(__builtin_inf, CEXT) () ++#define I 1i ++ ++/* Helpers to make the following code slightly less gross. */ ++#define COPYSIGN CONCAT2(__builtin_copysign, CEXT) ++#define FABS CONCAT2(__builtin_fabs, CEXT) ++ ++/* Verify that MTYPE matches up with CEXT. */ ++extern void *compile_type_assert[sizeof(INFINITY) == sizeof(MTYPE) ? 1 : -1]; ++ ++/* Ensure that we've lost any extra precision. */ ++#if NOTRUNC ++# define TRUNC(x) ++#else ++# define TRUNC(x) __asm__ ("" : "=m"(x) : "m"(x)) ++#endif ++ ++#if defined(L_mulsc3) || defined(L_muldc3) \ ++ || defined(L_mulxc3) || defined(L_multc3) ++ ++CTYPE ++CONCAT3(__mul,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d) ++{ ++ MTYPE ac, bd, ad, bc, x, y; ++ ++ ac = a * c; ++ bd = b * d; ++ ad = a * d; ++ bc = b * c; ++ ++ TRUNC (ac); ++ TRUNC (bd); ++ TRUNC (ad); ++ TRUNC (bc); ++ ++ x = ac - bd; ++ y = ad + bc; ++ ++ if (isnan (x) && isnan (y)) ++ { ++ /* Recover infinities that computed as NaN + iNaN. */ ++ _Bool recalc = 0; ++ if (isinf (a) || isinf (b)) ++ { ++ /* z is infinite. "Box" the infinity and change NaNs in ++ the other factor to 0. */ ++ a = COPYSIGN (isinf (a) ? 1 : 0, a); ++ b = COPYSIGN (isinf (b) ? 1 : 0, b); ++ if (isnan (c)) c = COPYSIGN (0, c); ++ if (isnan (d)) d = COPYSIGN (0, d); ++ recalc = 1; ++ } ++ if (isinf (c) || isinf (d)) ++ { ++ /* w is infinite. "Box" the infinity and change NaNs in ++ the other factor to 0. */ ++ c = COPYSIGN (isinf (c) ? 1 : 0, c); ++ d = COPYSIGN (isinf (d) ? 1 : 0, d); ++ if (isnan (a)) a = COPYSIGN (0, a); ++ if (isnan (b)) b = COPYSIGN (0, b); ++ recalc = 1; ++ } ++ if (!recalc ++ && (isinf (ac) || isinf (bd) ++ || isinf (ad) || isinf (bc))) ++ { ++ /* Recover infinities from overflow by changing NaNs to 0. */ ++ if (isnan (a)) a = COPYSIGN (0, a); ++ if (isnan (b)) b = COPYSIGN (0, b); ++ if (isnan (c)) c = COPYSIGN (0, c); ++ if (isnan (d)) d = COPYSIGN (0, d); ++ recalc = 1; ++ } ++ if (recalc) ++ { ++ x = INFINITY * (a * c - b * d); ++ y = INFINITY * (a * d + b * c); ++ } ++ } ++ ++ return x + I * y; ++} ++#endif /* complex multiply */ ++ ++#if defined(L_divsc3) || defined(L_divdc3) \ ++ || defined(L_divxc3) || defined(L_divtc3) ++ ++CTYPE ++CONCAT3(__div,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d) ++{ ++ MTYPE denom, ratio, x, y; ++ ++ /* ??? We can get better behavior from logarithmic scaling instead of ++ the division. But that would mean starting to link libgcc against ++ libm. We could implement something akin to ldexp/frexp as gcc builtins ++ fairly easily... */ ++ if (FABS (c) < FABS (d)) ++ { ++ ratio = c / d; ++ denom = (c * ratio) + d; ++ x = ((a * ratio) + b) / denom; ++ y = ((b * ratio) - a) / denom; ++ } ++ else ++ { ++ ratio = d / c; ++ denom = (d * ratio) + c; ++ x = ((b * ratio) + a) / denom; ++ y = (b - (a * ratio)) / denom; ++ } ++ ++ /* Recover infinities and zeros that computed as NaN+iNaN; the only cases ++ are nonzero/zero, infinite/finite, and finite/infinite. */ ++ if (isnan (x) && isnan (y)) ++ { ++ if (c == 0.0 && d == 0.0 && (!isnan (a) || !isnan (b))) ++ { ++ x = COPYSIGN (INFINITY, c) * a; ++ y = COPYSIGN (INFINITY, c) * b; ++ } ++ else if ((isinf (a) || isinf (b)) && isfinite (c) && isfinite (d)) ++ { ++ a = COPYSIGN (isinf (a) ? 1 : 0, a); ++ b = COPYSIGN (isinf (b) ? 1 : 0, b); ++ x = INFINITY * (a * c + b * d); ++ y = INFINITY * (b * c - a * d); ++ } ++ else if ((isinf (c) || isinf (d)) && isfinite (a) && isfinite (b)) ++ { ++ c = COPYSIGN (isinf (c) ? 1 : 0, c); ++ d = COPYSIGN (isinf (d) ? 1 : 0, d); ++ x = 0.0 * (a * c + b * d); ++ y = 0.0 * (b * c - a * d); ++ } ++ } ++ ++ return x + I * y; ++} ++#endif /* complex divide */ ++ ++#endif /* all complex float routines */ ++ + /* From here on down, the routines use normal data types. */ + + #define SItype bogus_type diff --git a/SOURCES/gcc34-libgcc_eh-hidden.patch b/SOURCES/gcc34-libgcc_eh-hidden.patch new file mode 100644 index 0000000..2131bd3 --- /dev/null +++ b/SOURCES/gcc34-libgcc_eh-hidden.patch @@ -0,0 +1,31 @@ +--- gcc/mklibgcc.in.jj 2005-11-21 08:57:19.000000000 -0500 ++++ gcc/mklibgcc.in 2006-05-23 09:12:19.000000000 -0400 +@@ -490,10 +490,26 @@ EOF + + if [ "$SHLIB_LINK" ]; then + ++ if [ "@libgcc_visibility@" = yes ]; then ++ libgcc_eh_static_objS= ++ echo "" ++ for o in $libgcc_eh_static_objs; do ++ # .oS objects will have all non-local symbol definitions .hidden ++ oS=`echo ${o} | sed s~${objext}'$~.oS~g'` ++ echo "${oS}: stmp-dirs libgcc/${dir}/stacknote.s ${o}" ++ # non-GNU nm emits three fields even for undefined and typeless symbols, ++ # so explicitly omit them ++ echo ' ( $(NM_FOR_TARGET) '${SHLIB_NM_FLAGS} ${o}' | $(AWK) '\''NF == 3 && $$2 !~ /^[UN]$$/ { print "\t.hidden", $$3 }'\''; cat libgcc/${dir}/stacknote.s ) | $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) '${flags}' -r -nostdinc -nostdlib -o $@ '${o}' -xassembler -' ++ libgcc_eh_static_objS="${libgcc_eh_static_objS} ${oS}" ++ done ++ else ++ libgcc_eh_static_objS="$libgcc_eh_static_objs" ++ fi ++ + echo "" +- echo "${dir}/libgcc_eh.a: stmp-dirs $libgcc_eh_static_objs" ++ echo "${dir}/libgcc_eh.a: stmp-dirs $libgcc_eh_static_objS" + echo " -rm -rf ${dir}/libgcc_eh.a" +- echo ' $(AR_CREATE_FOR_TARGET)' ${dir}/libgcc_eh.a $libgcc_eh_static_objs ++ echo ' $(AR_CREATE_FOR_TARGET)' ${dir}/libgcc_eh.a $libgcc_eh_static_objS + echo ' $(RANLIB_FOR_TARGET)' ${dir}/libgcc_eh.a + + if [ -z "$SHLIB_MULTILIB" ]; then diff --git a/SOURCES/gcc34-makeinfo.patch b/SOURCES/gcc34-makeinfo.patch new file mode 100644 index 0000000..2451ca3 --- /dev/null +++ b/SOURCES/gcc34-makeinfo.patch @@ -0,0 +1,27 @@ +2007-09-23 Jakub Jelinek + + * configure.ac (MAKEINFO): Handle makeinfo version 4.10 and above. + * configure: Regenerated. + +--- gcc/configure.ac.jj 2007-10-16 21:18:08.000000000 +0200 ++++ gcc/configure.ac 2007-10-16 21:18:08.000000000 +0200 +@@ -648,7 +648,7 @@ else + # that we can use it. + gcc_AC_CHECK_PROG_VER(MAKEINFO, makeinfo, --version, + [GNU texinfo.* \([0-9][0-9.]*\)], +- [4.[2-9]*]) ++ [4.[2-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*]) + fi + + if test $gcc_cv_prog_makeinfo_modern = no; then +--- gcc/configure.jj 2005-11-21 14:43:20.000000000 +0100 ++++ gcc/configure 2007-10-16 21:19:11.000000000 +0200 +@@ -5232,7 +5232,7 @@ else + echo "configure:5232: version of makeinfo is $ac_prog_version" >&5 + case $ac_prog_version in + '') gcc_cv_prog_makeinfo_modern=no;; +- 4.[2-9]*) ++ 4.[2-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*) + gcc_cv_prog_makeinfo_modern=yes;; + *) gcc_cv_prog_makeinfo_modern=no;; + esac diff --git a/SOURCES/gcc34-multi32-hack.patch b/SOURCES/gcc34-multi32-hack.patch new file mode 100644 index 0000000..1c3ffce --- /dev/null +++ b/SOURCES/gcc34-multi32-hack.patch @@ -0,0 +1,68 @@ +This is an optimization hack which should only be present +in a sparc 32bit driver of the compiler compiled with +host/target/build sparc64-redhat-linux --with-cpu=v7. +As long long HOST_WIDE_INT slows things down, we can have in +addition to the sparc64-*/3.2/{cc1,cc1plus} +sparc-*/3.2/{cc1,cc1plus} binaries which are suitable for compiling +-m32 code only, but use long HOST_WIDE_INT. + +--- gcc/gcc.c.jj 2003-05-15 18:06:04.000000000 -0400 ++++ gcc/gcc.c 2003-05-20 10:31:15.000000000 -0400 +@@ -3084,6 +3084,8 @@ process_command (int argc, const char *c + int have_c = 0; + int have_o = 0; + int lang_n_infiles = 0; ++ int m64 = 0; ++ int used_B = 0; + #ifdef MODIFY_TARGET_NAME + int is_modify_target_name; + int j; +@@ -3602,6 +3604,7 @@ warranty; not even for MERCHANTABILITY o + PREFIX_PRIORITY_B_OPT, 0, &warn_B, 0); + add_prefix (&include_prefixes, concat (value, "include", NULL), + NULL, PREFIX_PRIORITY_B_OPT, 0, NULL, 0); ++ used_B = 1; + n_switches++; + } + break; +@@ -3664,6 +3667,13 @@ warranty; not even for MERCHANTABILITY o + #endif + goto normal_switch; + ++ /* HACK START */ ++ case 'm': ++ if (p[1] == '6' && p[2] == '4') ++ m64 = 1; ++ /* FALLTHROUGH */ ++ /* HACK END */ ++ + default: + normal_switch: + +@@ -3741,6 +3751,26 @@ warranty; not even for MERCHANTABILITY o + /* Use 2 as fourth arg meaning try just the machine as a suffix, + as well as trying the machine and the version. */ + #ifndef OS2 ++ /* HACK START */ ++ if (!m64 && !used_B && !strncmp (spec_machine, "sparc64-", 8)) ++ { ++ const char *sparc32_exec_prefix = ++ concat (standard_libexec_prefix, "sparc-", spec_machine + 8, ++ dir_separator_str, spec_version, dir_separator_str, NULL); ++ add_prefix (&exec_prefixes, sparc32_exec_prefix, "GCC", ++ PREFIX_PRIORITY_LAST, 0, warn_std_ptr, 0); ++ } ++ /* HACK END */ ++ /* HACK START */ ++ if (!m64 && !used_B && !strncmp (spec_machine, "ppc64-", 6)) ++ { ++ const char *ppc32_exec_prefix = ++ concat (standard_libexec_prefix, "ppc-", spec_machine + 6, ++ dir_separator_str, spec_version, dir_separator_str, NULL); ++ add_prefix (&exec_prefixes, ppc32_exec_prefix, "GCC", ++ PREFIX_PRIORITY_LAST, 0, warn_std_ptr, 0); ++ } ++ /* HACK END */ + add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC", + PREFIX_PRIORITY_LAST, 1, warn_std_ptr, 0); + add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS", diff --git a/SOURCES/gcc34-ppc64-m32-m64-multilib-only.patch b/SOURCES/gcc34-ppc64-m32-m64-multilib-only.patch new file mode 100644 index 0000000..b518389 --- /dev/null +++ b/SOURCES/gcc34-ppc64-m32-m64-multilib-only.patch @@ -0,0 +1,22 @@ +--- gcc/config/rs6000/t-linux64 2003-06-03 05:11:45.000000000 -0400 ++++ gcc/config/rs6000/t-linux64 2003-06-11 17:07:16.000000000 -0400 +@@ -9,13 +9,13 @@ TARGET_LIBGCC2_CFLAGS = -mno-minimal-toc + + SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-ppc64.ver + +-MULTILIB_OPTIONS = m64/m32 msoft-float +-MULTILIB_DIRNAMES = 64 32 nof ++MULTILIB_OPTIONS = m64/m32 ++MULTILIB_DIRNAMES = 64 32 + MULTILIB_EXTRA_OPTS = fPIC mstrict-align +-MULTILIB_EXCEPTIONS = m64/msoft-float +-MULTILIB_EXCLUSIONS = m64/!m32/msoft-float +-MULTILIB_OSDIRNAMES = ../lib64 ../lib nof +-MULTILIB_MATCHES = $(MULTILIB_MATCHES_FLOAT) ++MULTILIB_EXCEPTIONS = ++MULTILIB_EXCLUSIONS = ++MULTILIB_OSDIRNAMES = ../lib64 ../lib ++MULTILIB_MATCHES = + + # We want fine grained libraries, so use the new code to build the + # floating point emulation libraries. diff --git a/SOURCES/gcc34-pr11953.patch b/SOURCES/gcc34-pr11953.patch new file mode 100644 index 0000000..af95bd6 --- /dev/null +++ b/SOURCES/gcc34-pr11953.patch @@ -0,0 +1,39 @@ +2006-02-17 Jakub Jelinek + + PR libstdc++/11953 + * gthr-posix.h (_REENTRANT): Only define if __osf__ is defined. + + * config/ia64/linux.h (CPP_SPEC): Define. + * config/s390/linux.h (CPP_SPEC): Define. + +--- gcc/gthr-posix.h (revision 111211) ++++ gcc/gthr-posix.h (revision 111212) +@@ -36,7 +36,7 @@ Software Foundation, 51 Franklin Street, + #define __GTHREADS 1 + + /* Some implementations of require this to be defined. */ +-#ifndef _REENTRANT ++#if !defined(_REENTRANT) && defined(__osf__) + #define _REENTRANT 1 + #endif + +--- gcc/config/s390/linux.h (revision 111211) ++++ gcc/config/s390/linux.h (revision 111212) +@@ -89,6 +89,7 @@ Software Foundation, 51 Franklin Street, + %{m31:-dynamic-linker /lib/ld.so.1} \ + %{m64:-dynamic-linker /lib64/ld64.so.1}}}}" + ++#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" + + #define TARGET_ASM_FILE_END file_end_indicate_exec_stack + +--- gcc/config/ia64/linux.h (revision 111211) ++++ gcc/config/ia64/linux.h (revision 111212) +@@ -48,6 +48,7 @@ do { \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux-ia64.so.2}} \ + %{static:-static}}" + ++#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" + + #define JMP_BUF_SIZE 76 + diff --git a/SOURCES/gcc34-pr14084.patch b/SOURCES/gcc34-pr14084.patch new file mode 100644 index 0000000..f82e2a3 --- /dev/null +++ b/SOURCES/gcc34-pr14084.patch @@ -0,0 +1,107 @@ +2004-05-27 Josef Zlomek + + PR middle-end/14084 + * emit-rtl.c (gen_rtx_REG_offset): Adjust the offset according + to size of decl. + +--- gcc/emit-rtl.c 25 May 2004 12:04:15 -0000 1.391 ++++ gcc/emit-rtl.c 27 May 2004 04:28:12 -0000 1.392 +@@ -746,13 +746,96 @@ gen_reg_rtx (enum machine_mode mode) + return val; + } + +-/* Generate a register with same attributes as REG, +- but offsetted by OFFSET. */ ++/* Generate a register with same attributes as REG, but offsetted by OFFSET. ++ Do the big endian correction if needed. */ + + rtx + gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, int offset) + { + rtx new = gen_rtx_REG (mode, regno); ++ tree decl; ++ HOST_WIDE_INT var_size; ++ ++ /* PR middle-end/14084 ++ The problem appears when a variable is stored in a larger register ++ and later it is used in the original mode or some mode in between ++ or some part of variable is accessed. ++ ++ On little endian machines there is no problem because ++ the REG_OFFSET of the start of the variable is the same when ++ accessed in any mode (it is 0). ++ ++ However, this is not true on big endian machines. ++ The offset of the start of the variable is different when accessed ++ in different modes. ++ When we are taking a part of the REG we have to change the OFFSET ++ from offset WRT size of mode of REG to offset WRT size of variable. ++ ++ If we would not do the big endian correction the resulting REG_OFFSET ++ would be larger than the size of the DECL. ++ ++ Examples of correction, for BYTES_BIG_ENDIAN WORDS_BIG_ENDIAN machine: ++ ++ REG.mode MODE DECL size old offset new offset description ++ DI SI 4 4 0 int32 in SImode ++ DI SI 1 4 0 char in SImode ++ DI QI 1 7 0 char in QImode ++ DI QI 4 5 1 1st element in QImode ++ of char[4] ++ DI HI 4 6 2 1st element in HImode ++ of int16[2] ++ ++ If the size of DECL is equal or greater than the size of REG ++ we can't do this correction because the register holds the ++ whole variable or a part of the variable and thus the REG_OFFSET ++ is already correct. */ ++ ++ decl = REG_EXPR (reg); ++ if ((BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN) ++ && decl != NULL ++ && offset > 0 ++ && GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode) ++ && ((var_size = int_size_in_bytes (TREE_TYPE (decl))) > 0 ++ && var_size < GET_MODE_SIZE (GET_MODE (reg)))) ++ { ++ int offset_le; ++ ++ /* Convert machine endian to little endian WRT size of mode of REG. */ ++ if (WORDS_BIG_ENDIAN) ++ offset_le = ((GET_MODE_SIZE (GET_MODE (reg)) - 1 - offset) ++ / UNITS_PER_WORD) * UNITS_PER_WORD; ++ else ++ offset_le = (offset / UNITS_PER_WORD) * UNITS_PER_WORD; ++ ++ if (BYTES_BIG_ENDIAN) ++ offset_le += ((GET_MODE_SIZE (GET_MODE (reg)) - 1 - offset) ++ % UNITS_PER_WORD); ++ else ++ offset_le += offset % UNITS_PER_WORD; ++ ++ if (offset_le >= var_size) ++ { ++ /* MODE is wider than the variable so the new reg will cover ++ the whole variable so the resulting OFFSET should be 0. */ ++ offset = 0; ++ } ++ else ++ { ++ /* Convert little endian to machine endian WRT size of variable. */ ++ if (WORDS_BIG_ENDIAN) ++ offset = ((var_size - 1 - offset_le) ++ / UNITS_PER_WORD) * UNITS_PER_WORD; ++ else ++ offset = (offset_le / UNITS_PER_WORD) * UNITS_PER_WORD; ++ ++ if (BYTES_BIG_ENDIAN) ++ offset += ((var_size - 1 - offset_le) ++ % UNITS_PER_WORD); ++ else ++ offset += offset_le % UNITS_PER_WORD; ++ } ++ } ++ + REG_ATTRS (new) = get_reg_attrs (REG_EXPR (reg), + REG_OFFSET (reg) + offset); + return new; diff --git a/SOURCES/gcc34-pr16104.patch b/SOURCES/gcc34-pr16104.patch new file mode 100644 index 0000000..034bb96 --- /dev/null +++ b/SOURCES/gcc34-pr16104.patch @@ -0,0 +1,97 @@ +2005-01-13 Jakub Jelinek + + PR rtl-optimization/16104 + * expr.c (convert_move): Handle vector from resp. to if mode + sizes differ. + + * gcc.c-torture/execute/20050113-1.c: New test. + +--- gcc/expr.c.jj 2004-12-27 21:31:08.000000000 +0100 ++++ gcc/expr.c 2005-01-13 15:56:31.229253647 +0100 +@@ -590,7 +590,26 @@ convert_move (rtx to, rtx from, int unsi + if (VECTOR_MODE_P (to_mode) || VECTOR_MODE_P (from_mode)) + { + if (GET_MODE_BITSIZE (from_mode) != GET_MODE_BITSIZE (to_mode)) +- abort (); ++ { ++ if (VECTOR_MODE_P (from_mode)) ++ { ++ enum machine_mode new_mode; ++ ++ new_mode = mode_for_size (GET_MODE_BITSIZE (from_mode), ++ MODE_INT, 0); ++ from = simplify_gen_subreg (new_mode, from, from_mode, 0); ++ } ++ if (VECTOR_MODE_P (to_mode)) ++ { ++ enum machine_mode new_mode; ++ ++ new_mode = mode_for_size (GET_MODE_BITSIZE (to_mode), ++ MODE_INT, 0); ++ to = simplify_gen_subreg (new_mode, to, to_mode, 0); ++ } ++ convert_move (to, from, unsignedp); ++ return; ++ } + + if (VECTOR_MODE_P (to_mode)) + from = simplify_gen_subreg (to_mode, from, GET_MODE (from), 0); +--- gcc/testsuite/gcc.c-torture/execute/20050113-1.c.jj 2005-01-13 15:51:09.194383356 +0100 ++++ gcc/testsuite/gcc.c-torture/execute/20050113-1.c 2005-01-13 15:37:22.000000000 +0100 +@@ -0,0 +1,56 @@ ++/* PR rtl-optimization/16104 */ ++ ++extern void abort (void); ++ ++typedef int V2SI __attribute__ ((vector_size (8))); ++typedef short V2HI __attribute__ ((vector_size (4))); ++ ++int ++test1 (void) ++{ ++ return (long long) (V2SI) 0LL; ++} ++ ++int ++test2 (V2SI x) ++{ ++ return (long long) x; ++} ++ ++V2SI ++test3 (void) ++{ ++ return (V2SI) (long long) (int) (V2HI) 0; ++} ++ ++V2SI ++test4 (V2HI x) ++{ ++ return (V2SI) (long long) (int) x; ++} ++ ++int ++main (void) ++{ ++ if (sizeof (short) != 2 || sizeof (int) != 4 || sizeof (long long) != 8) ++ return 0; ++ ++ if (test1 () != 0) ++ abort (); ++ ++ V2SI x = { 2, 2 }; ++ if (test2 (x) != 2) ++ abort (); ++ ++ union { V2SI x; int y[2]; } u; ++ u.x = test3 (); ++ if (u.y[0] != 0 || u.y[1] != 0) ++ abort (); ++ ++ V2HI y = { 4, 4 }; ++ union { V2SI x; long long y; } v; ++ v.x = test4 (y); ++ if (v.y != 0x40004) ++ abort (); ++ return 0; ++} diff --git a/SOURCES/gcc34-pr18300.patch b/SOURCES/gcc34-pr18300.patch new file mode 100644 index 0000000..21da422 --- /dev/null +++ b/SOURCES/gcc34-pr18300.patch @@ -0,0 +1,166 @@ +2005-09-07 Jakub Jelinek + + PR target/18300 + * config/i386/i386.c (classify_argument): Only use different + iterators for nested loops if nested loops sharing the same + iterator would hang. + +2004-11-13 Zak Kipling + + PR target/18300 + * config/i386/i386.c (classify_argument): Fix infinite loop when + passing object with 3 or more base classes by value. + +--- gcc/config/i386/i386.c.jj 2005-07-21 11:01:36.000000000 +0200 ++++ gcc/config/i386/i386.c 2005-09-07 14:22:19.000000000 +0200 +@@ -2028,8 +2028,17 @@ classify_argument (enum machine_mode mod + { + tree bases = TYPE_BINFO_BASETYPES (type); + int n_bases = TREE_VEC_LENGTH (bases); +- int i; +- ++ int i, basenum; ++ enum x86_64_reg_class saveclasses[MAX_CLASSES]; ++ bool seen[MAX_CLASSES]; ++ ++ /* PR target/18300: The following code mistakenly uses the same ++ iterator variable in both nested for loops. But to preserve ++ binary compatibility, do whatever this code used to do before ++ unless old GCC would hang in an infinite loop. In that case ++ use whatever GCC 4.0+ does. */ ++ memset (seen, 0, sizeof (seen)); ++ memcpy (saveclasses, classes, sizeof (saveclasses)); + for (i = 0; i < n_bases; ++i) + { + tree binfo = TREE_VEC_ELT (bases, i); +@@ -2037,6 +2046,12 @@ classify_argument (enum machine_mode mod + int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8; + tree type = BINFO_TYPE (binfo); + ++ if (i < MAX_CLASSES) ++ { ++ if (seen[i]) ++ break; ++ seen[i] = true; ++ } + num = classify_argument (TYPE_MODE (type), + type, subclasses, + (offset + bit_offset) % 256); +@@ -2049,6 +2064,32 @@ classify_argument (enum machine_mode mod + merge_classes (subclasses[i], classes[i + pos]); + } + } ++ if (i < n_bases) ++ { ++ /* Older GCC 3.[0-4].x would hang in the above loop, so ++ don't worry about backwards compatibility and ++ just DTRT. */ ++ memcpy (classes, saveclasses, sizeof (saveclasses)); ++ for (basenum = 0; basenum < n_bases; ++basenum) ++ { ++ tree binfo = TREE_VEC_ELT (bases, basenum); ++ int num; ++ int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8; ++ tree type = BINFO_TYPE (binfo); ++ ++ num = classify_argument (TYPE_MODE (type), ++ type, subclasses, ++ (offset + bit_offset) % 256); ++ if (!num) ++ return 0; ++ for (i = 0; i < num; i++) ++ { ++ int pos = (offset + (bit_offset % 64)) / 8 / 8; ++ classes[i + pos] = ++ merge_classes (subclasses[i], classes[i + pos]); ++ } ++ } ++ } + } + /* And now merge the fields of structure. */ + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) +@@ -2116,8 +2157,17 @@ classify_argument (enum machine_mode mod + { + tree bases = TYPE_BINFO_BASETYPES (type); + int n_bases = TREE_VEC_LENGTH (bases); +- int i; +- ++ int i, basenum; ++ enum x86_64_reg_class saveclasses[MAX_CLASSES]; ++ bool seen[MAX_CLASSES]; ++ ++ /* PR target/18300: The following code mistakenly uses the same ++ iterator variable in both nested for loops. But to preserve ++ binary compatibility, do whatever this code used to do before ++ unless old GCC would hang in an infinite loop. In that case ++ use whatever GCC 4.0+ does. */ ++ memset (seen, 0, sizeof (seen)); ++ memcpy (saveclasses, classes, sizeof (saveclasses)); + for (i = 0; i < n_bases; ++i) + { + tree binfo = TREE_VEC_ELT (bases, i); +@@ -2125,6 +2175,12 @@ classify_argument (enum machine_mode mod + int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8; + tree type = BINFO_TYPE (binfo); + ++ if (i < MAX_CLASSES) ++ { ++ if (seen[i]) ++ break; ++ seen[i] = true; ++ } + num = classify_argument (TYPE_MODE (type), + type, subclasses, + (offset + (bit_offset % 64)) % 256); +@@ -2137,6 +2193,32 @@ classify_argument (enum machine_mode mod + merge_classes (subclasses[i], classes[i + pos]); + } + } ++ if (i < n_bases) ++ { ++ /* Older GCC 3.[0-4].x would hang in the above loop, so ++ don't worry about backwards compatibility and ++ just DTRT. */ ++ memcpy (classes, saveclasses, sizeof (saveclasses)); ++ for (basenum = 0; basenum < n_bases; ++basenum) ++ { ++ tree binfo = TREE_VEC_ELT (bases, basenum); ++ int num; ++ int offset = tree_low_cst (BINFO_OFFSET (binfo), 0) * 8; ++ tree type = BINFO_TYPE (binfo); ++ ++ num = classify_argument (TYPE_MODE (type), ++ type, subclasses, ++ (offset + (bit_offset % 64)) % 256); ++ if (!num) ++ return 0; ++ for (i = 0; i < num; i++) ++ { ++ int pos = (offset + (bit_offset % 64)) / 8 / 8; ++ classes[i + pos] = ++ merge_classes (subclasses[i], classes[i + pos]); ++ } ++ } ++ } + } + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { +--- gcc/testsuite/g++.dg/other/infloop-1.C 1 Jan 1970 00:00:00 -0000 ++++ gcc/testsuite/g++.dg/other/infloop-1.C 13 Nov 2004 23:09:08 -0000 1.1 +@@ -0,0 +1,16 @@ ++// PR 18300: This sends old compilers into an infinite loop on x86_64 ++// Testcase and patch contributed by Zak Kipling ++ ++struct base1 { }; ++struct base2 { }; ++struct base3 { }; ++ ++struct derived : base1, base2, base3 { }; ++ ++void foo(derived); ++ ++int main() ++{ ++ foo(derived()); ++} ++ diff --git a/SOURCES/gcc34-pr18925.patch b/SOURCES/gcc34-pr18925.patch new file mode 100644 index 0000000..7256098 --- /dev/null +++ b/SOURCES/gcc34-pr18925.patch @@ -0,0 +1,48 @@ +2004-12-13 Mark Mitchell + + PR c++/18925 + * class.c (layout_class_type): Determine the visibility of static + data members. + + * g++.dg/ext/visibility/staticdatamem.C: New test. + +--- gcc/cp/class.c 8 Dec 2004 08:35:33 -0000 1.692 ++++ gcc/cp/class.c 14 Dec 2004 02:21:46 -0000 1.693 +@@ -4553,7 +4553,13 @@ layout_class_type (tree t, tree *virtual + At this point, finish_record_layout will be called, but + S1 is still incomplete.) */ + if (TREE_CODE (field) == VAR_DECL) +- maybe_register_incomplete_var (field); ++ { ++ maybe_register_incomplete_var (field); ++ /* The visibility of static data members is determined ++ at their point of declaration, not their point of ++ definition. */ ++ determine_visibility (field); ++ } + continue; + } + +--- gcc/testsuite/g++.dg/ext/visibility/staticdatamem.C 1 Jan 1970 00:00:00 -0000 ++++ gcc/testsuite/g++.dg/ext/visibility/staticdatamem.C 14 Dec 2004 02:15:55 -0000 1.1 +@@ -0,0 +1,20 @@ ++// PR c++/18925 ++// { dg-do compile { target ia64-*-linux* } } ++// { dg-options "-fPIC -fvisibility=hidden" } ++// { dg-final { scan-assembler-not "gprel" } } ++ ++class __attribute__ ((visibility("default"))) Type ++{ ++ private: ++ static long _staticTypeCount; ++ public: ++ Type() { _staticTypeCount++; } ++ ~Type(); ++}; ++ ++long Type::_staticTypeCount = 0; ++ ++Type::~Type() ++{ ++ _staticTypeCount--; ++} diff --git a/SOURCES/gcc34-pr21412.patch b/SOURCES/gcc34-pr21412.patch new file mode 100644 index 0000000..58d829a --- /dev/null +++ b/SOURCES/gcc34-pr21412.patch @@ -0,0 +1,136 @@ +2005-05-07 Richard Henderson + + PR target/21412 + * config/rs6000/rs6000.c (rs6000_emit_move): Look for tls addresses + with constant offsets. + +2004-07-11 Ulrich Weigand + + * config/s390/s390.c (legitimize_tls_address): Handle constant offsets + added to TLS symbol addresses. + +2004-07-06 Richard Henderson + + * config/i386/i386.c (legitimize_address): Handle CONST with TLS + operand. + (ix86_expand_move): Don't call legitimize_pic_address directly. + +2006-05-05 Jakub Jelinek + + * gcc.dg/tls/opt-12.c: New test. + +--- gcc/config/s390/s390.c (revision 84404) ++++ gcc/config/s390/s390.c (revision 84535) +@@ -2913,6 +2913,18 @@ legitimize_tls_address (rtx addr, rtx re + } + } + ++ else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == PLUS ++ && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT) ++ { ++ new = XEXP (XEXP (addr, 0), 0); ++ if (GET_CODE (new) != SYMBOL_REF) ++ new = gen_rtx_CONST (Pmode, new); ++ ++ new = legitimize_tls_address (new, reg); ++ new = plus_constant (new, INTVAL (XEXP (XEXP (addr, 0), 1))); ++ new = force_operand (new, 0); ++ } ++ + else + abort (); /* for now ... */ + +--- gcc/config/i386/i386.c 2005-11-21 14:56:49.000000000 +0100 ++++ gcc/config/i386/i386.c 2006-05-05 11:21:54.000000000 +0200 +@@ -6604,6 +6604,13 @@ legitimize_address (rtx x, rtx oldx ATTR + log = tls_symbolic_operand (x, mode); + if (log) + return legitimize_tls_address (x, log, false); ++ if (GET_CODE (x) == CONST ++ && GET_CODE (XEXP (x, 0)) == PLUS ++ && (log = tls_symbolic_operand (XEXP (XEXP (x, 0), 0), Pmode))) ++ { ++ rtx t = legitimize_tls_address (XEXP (XEXP (x, 0), 0), log, false); ++ return gen_rtx_PLUS (Pmode, t, XEXP (XEXP (x, 0), 1)); ++ } + + if (flag_pic && SYMBOLIC_CONST (x)) + return legitimize_pic_address (x, 0); +@@ -8395,6 +8402,10 @@ ix86_expand_move (enum machine_mode mode + #else + if (GET_CODE (op0) == MEM) + op1 = force_reg (Pmode, op1); ++ else if (GET_CODE (op1) == CONST ++ && GET_CODE (XEXP (op1, 0)) == PLUS ++ && tls_symbolic_operand (XEXP (XEXP (op1, 0), 0), Pmode)) ++ op1 = legitimize_address (op1, op1, Pmode); + else + { + rtx temp = op0; +--- gcc/config/rs6000/rs6000.c (revision 99334) ++++ gcc/config/rs6000/rs6000.c (revision 99367) +@@ -4436,11 +4436,31 @@ rs6000_emit_move (rtx dest, rtx source, + + /* Recognize the case where operand[1] is a reference to thread-local + data and load its address to a register. */ +- if (GET_CODE (operands[1]) == SYMBOL_REF) ++ if (rs6000_tls_referenced_p (operands[1])) + { +- enum tls_model model = SYMBOL_REF_TLS_MODEL (operands[1]); +- if (model != 0) +- operands[1] = rs6000_legitimize_tls_address (operands[1], model); ++ enum tls_model model; ++ rtx tmp = operands[1]; ++ rtx addend = NULL; ++ ++ if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS) ++ { ++ addend = XEXP (XEXP (tmp, 0), 1); ++ tmp = XEXP (XEXP (tmp, 0), 0); ++ } ++ ++ if (GET_CODE (tmp) != SYMBOL_REF) ++ abort (); ++ model = SYMBOL_REF_TLS_MODEL (tmp); ++ if (model == 0) ++ abort (); ++ ++ tmp = rs6000_legitimize_tls_address (tmp, model); ++ if (addend) ++ { ++ tmp = gen_rtx_PLUS (mode, tmp, addend); ++ tmp = force_operand (tmp, operands[0]); ++ } ++ operands[1] = tmp; + } + + /* Handle the case where reload calls us with an invalid address. */ +--- gcc/testsuite/gcc.dg/tls/opt-9.c (revision 0) ++++ gcc/testsuite/gcc.dg/tls/opt-9.c (revision 99367) +@@ -0,0 +1,7 @@ ++/* PR 21412 */ ++/* { dg-do compile */ ++/* { dg-options "-O2 -fPIC" } */ ++ ++struct S { int x[10]; }; ++extern __thread struct S s; ++int *foo() { return &s.x[2]; } +--- gcc/testsuite/gcc.dg/tls/opt-12.c 2006-04-19 19:21:31.748476000 +0200 ++++ gcc/testsuite/gcc.dg/tls/opt-12.c 2006-05-05 11:01:33.000000000 +0200 +@@ -0,0 +1,16 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2" } */ ++/* { XXdgXX-require-effective-target tls } */ ++ ++__thread struct ++{ ++ int a; ++ char b[32]; ++} thr; ++ ++int ++main () ++{ ++ __builtin_strcpy (thr.b, "abcd"); ++ return 0; ++} diff --git a/SOURCES/gcc34-pr21955.patch b/SOURCES/gcc34-pr21955.patch new file mode 100644 index 0000000..cf0e7f3 --- /dev/null +++ b/SOURCES/gcc34-pr21955.patch @@ -0,0 +1,410 @@ +2005-07-22 Jakub Jelinek + + * src/sstream-inst.cc: Add .hidden directive for + streamsize basic_stringbuf<{char,wchar_t}>::showmanyc(). + * src/sstream-inst-showmanyc.cc: New file. + * src/Makefile.am (libstdc++_nonshared.la): Add new library. + * src/Makefile.in: Rebuilt. + * testsuite/lib/libstdc++.exp: Append -lstdc++_nonshared for + testsuite executable linking. + +2005-06-08 Benjamin Kosnik + + PR libstdc++/21955 + * include/std/std_sstream.h (basic_stringbuf::showmanyc): Add. + * testsuite/27_io/basic_streambuf/in_avail/char/1.cc: New, test + base class behavior. + * testsuite/27_io/basic_streambuf/in_avail/wchar_t/1.cc: Same. + * testsuite/27_io/basic_stringbuf/in_avail/char/21955.cc: New. + * testsuite/27_io/basic_stringbuf/in_avail/char/1.cc: Match + filebuf behavior. + * testsuite/27_io/basic_stringbuf/str/char/1.cc: Same. + +--- libstdc++-v3/src/sstream-inst.cc.jj 2003-07-11 10:28:13.000000000 +0200 ++++ libstdc++-v3/src/sstream-inst.cc 2005-07-21 17:46:08.000000000 +0200 +@@ -60,3 +60,8 @@ namespace std + template class basic_stringstream; + #endif + } // namespace std ++ ++#ifdef PIC ++__asm (".hidden _ZNSt15basic_stringbufIcSt11char_traitsIcESaIcEE9showmanycEv"); ++__asm (".hidden _ZNSt15basic_stringbufIwSt11char_traitsIwESaIwEE9showmanycEv"); ++#endif +--- libstdc++-v3/src/sstream-inst-showmanyc.cc.jj 2005-07-21 21:27:40.000000000 +0200 ++++ libstdc++-v3/src/sstream-inst-showmanyc.cc 2005-07-22 09:16:58.000000000 +0200 +@@ -0,0 +1,39 @@ ++// Explicit instantiation file. ++ ++// Copyright (C) 2005 ++// Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 2, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING. If not, write to the Free ++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++// USA. ++ ++// As a special exception, you may use this file as part of a free software ++// library without restriction. Specifically, if other files instantiate ++// templates or use macros or inline functions from this file, or you compile ++// this file and link it with other files to produce an executable, this ++// file does not by itself cause the resulting executable to be covered by ++// the GNU General Public License. This exception does not however ++// invalidate any other reasons why the executable file might be covered by ++// the GNU General Public License. ++ ++#include ++ ++namespace std ++{ ++ // These symbols are hidden in libstdc++.so, as it is undesirable to export ++ // @@GLIBCXX_3.4.6 ++ template streamsize basic_stringbuf, allocator >::showmanyc(); ++ template streamsize basic_stringbuf, allocator >::showmanyc(); ++} // namespace std +--- libstdc++-v3/src/Makefile.am.jj 2004-04-20 15:55:47.000000000 +0200 ++++ libstdc++-v3/src/Makefile.am 2005-07-22 09:00:32.000000000 +0200 +@@ -25,7 +25,7 @@ + include $(top_srcdir)/fragment.am + + # Cross compiler support. +-toolexeclib_LTLIBRARIES = libstdc++.la ++toolexeclib_LTLIBRARIES = libstdc++.la libstdc++_nonshared.la + + # Symbol versioning for shared libraries. + if GLIBCXX_BUILD_VERSIONED_SHLIB +@@ -150,6 +150,11 @@ libstdc___la_DEPENDENCIES = ${version_de + libstdc___la_LDFLAGS = \ + -version-info $(libtool_VERSION) ${version_arg} -lm + ++libstdc___nonshared_la_SOURCES = \ ++ sstream-inst-showmanyc.cc ++libstdc___nonshared_la_LIBADD = ++libstdc___nonshared_la_DEPENDENCIES = $(libstdc___nonshared_la_LIBADD) ++libstdc___nonshared_la_LDFLAGS = -static + + # Use special rules for the deprecated source files so that they find + # deprecated include files. +@@ -159,6 +164,14 @@ strstream.lo: strstream.cc + strstream.o: strstream.cc + $(CXXCOMPILE) -I$(GLIBCXX_INCLUDE_DIR)/backward -Wno-deprecated -c $< + ++# Use special rules for libstdc++_nonshared.la files, as -prefer-pic ++# doesn't seem to work for some reason. ++sstream-inst-showmanyc.lo: sstream-inst-showmanyc.cc ++ $(LTCXXCOMPILE) -c $< \ ++ && cp -f .libs/sstream-inst-showmanyc.o sstream-inst-showmanyc.o ++sstream-inst-showmanyc.o: sstream-inst-showmanyc.cc ++ $(CXXCOMPILE) -fPIC -DPIC -c $< ++ + # Use special rules for the concept-checking instantiations so that all + # the generated template functions are also instantiated. Force the checks + # to be on so that the instantiations are actually seen. +--- libstdc++-v3/src/Makefile.in.jj 2004-04-20 15:55:47.000000000 +0200 ++++ libstdc++-v3/src/Makefile.in 2005-07-22 09:06:15.000000000 +0200 +@@ -221,7 +221,7 @@ WARN_CXXFLAGS = \ + AM_CPPFLAGS = $(GLIBCXX_INCLUDES) + + # Cross compiler support. +-toolexeclib_LTLIBRARIES = libstdc++.la ++toolexeclib_LTLIBRARIES = libstdc++.la libstdc++_nonshared.la + + # Symbol versioning for shared libraries. + @GLIBCXX_BUILD_VERSIONED_SHLIB_TRUE@version_arg = -Wl,--version-script=libstdc++-symbol.ver +@@ -308,6 +308,13 @@ libstdc___la_LDFLAGS = \ + -version-info $(libtool_VERSION) ${version_arg} -lm + + ++libstdc___nonshared_la_SOURCES = \ ++ sstream-inst-showmanyc.cc ++ ++libstdc___nonshared_la_LIBADD = ++libstdc___nonshared_la_DEPENDENCIES = $(libstdc___nonshared_la_LIBADD) ++libstdc___nonshared_la_LDFLAGS = -static ++ + # Use special rules for the deprecated source files so that they find + # deprecated include files. + GLIBCXX_INCLUDE_DIR = $(glibcxx_builddir)/include +@@ -379,6 +386,8 @@ am__objects_3 = allocator.lo codecvt.lo + $(am__objects_1) $(am__objects_2) + am_libstdc___la_OBJECTS = $(am__objects_3) + libstdc___la_OBJECTS = $(am_libstdc___la_OBJECTS) ++am_libstdc___nonshared_la_OBJECTS = sstream-inst-showmanyc.lo ++libstdc___nonshared_la_OBJECTS = $(am_libstdc___nonshared_la_OBJECTS) + + DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) + depcomp = +@@ -386,10 +395,10 @@ am__depfiles_maybe = + CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) + CXXLD = $(CXX) +-DIST_SOURCES = $(libstdc___la_SOURCES) ++DIST_SOURCES = $(libstdc___la_SOURCES) $(libstdc___nonshared_la_SOURCES) + DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/fragment.am \ + Makefile.am +-SOURCES = $(libstdc___la_SOURCES) ++SOURCES = $(libstdc___la_SOURCES) $(libstdc___nonshared_la_SOURCES) + + all: all-am + +@@ -430,6 +439,8 @@ clean-toolexeclibLTLIBRARIES: + done + libstdc++.la: $(libstdc___la_OBJECTS) $(libstdc___la_DEPENDENCIES) + $(CXXLINK) -rpath $(toolexeclibdir) $(libstdc___la_LDFLAGS) $(libstdc___la_OBJECTS) $(libstdc___la_LIBADD) $(LIBS) ++libstdc++_nonshared.la: $(libstdc___nonshared_la_OBJECTS) $(libstdc___nonshared_la_DEPENDENCIES) ++ $(CXXLINK) -rpath $(toolexeclibdir) $(libstdc___nonshared_la_LDFLAGS) $(libstdc___nonshared_la_OBJECTS) $(libstdc___nonshared_la_LIBADD) $(LIBS) + + mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core +@@ -674,6 +685,14 @@ strstream.lo: strstream.cc + strstream.o: strstream.cc + $(CXXCOMPILE) -I$(GLIBCXX_INCLUDE_DIR)/backward -Wno-deprecated -c $< + ++# Use special rules for libstdc++_nonshared.la files, as -prefer-pic ++# doesn't seem to work for some reason. ++sstream-inst-showmanyc.lo: sstream-inst-showmanyc.cc ++ $(LTCXXCOMPILE) -c $< \ ++ && cp -f .libs/sstream-inst-showmanyc.o sstream-inst-showmanyc.o ++sstream-inst-showmanyc.o: sstream-inst-showmanyc.cc ++ $(CXXCOMPILE) -fPIC -DPIC -c $< ++ + # Use special rules for the concept-checking instantiations so that all + # the generated template functions are also instantiated. Force the checks + # to be on so that the instantiations are actually seen. +--- libstdc++-v3/include/std/std_sstream.h.jj 2004-10-04 14:58:25.000000000 +0200 ++++ libstdc++-v3/include/std/std_sstream.h 2005-07-21 17:17:16.000000000 +0200 +@@ -185,6 +185,18 @@ namespace std + _M_sync(const_cast(_M_string.data()), 0, __len); + } + ++ virtual streamsize ++ showmanyc() ++ { ++ streamsize __ret = -1; ++ if (_M_mode & ios_base::in) ++ { ++ _M_update_egptr(); ++ __ret = this->egptr() - this->gptr(); ++ } ++ return __ret; ++ } ++ + // [documentation is inherited] + virtual int_type + underflow(); +--- libstdc++-v3/testsuite/27_io/basic_stringbuf/str/char/1.cc.jj 2003-10-01 12:12:11.000000000 +0200 ++++ libstdc++-v3/testsuite/27_io/basic_stringbuf/str/char/1.cc 2005-07-22 01:22:15.000000000 +0200 +@@ -45,7 +45,7 @@ void test03() + std::streamsize d1 = strb_01.in_avail(); + std::streamsize d2 = strb_03.in_avail(); + VERIFY( d1 ); // non-zero +- VERIFY( !d2 ); // zero, cuz ios_base::out ++ VERIFY( d2 == -1 ); // -1, cuz ios_base::out + VERIFY( d1 != d2 ); //these should be the same + VERIFY( static_cast(str_01.length()) == d1 ); + VERIFY( strb_01.str() == strb_03.str() ); //ditto +--- libstdc++-v3/testsuite/27_io/basic_stringbuf/in_avail/char/1.cc.jj 2003-10-01 12:12:10.000000000 +0200 ++++ libstdc++-v3/testsuite/27_io/basic_stringbuf/in_avail/char/1.cc 2005-07-22 01:22:04.000000000 +0200 +@@ -49,8 +49,8 @@ void test04() + VERIFY( strmof_1 == static_cast(str_01.length()) ); + VERIFY( strmof_2 == static_cast(str_02.length()) ); + strmof_1 = strb_03.in_avail(); +- // zero cuz write-only, or eof()? zero, from showmany +- VERIFY( strmof_1 == 0 ); ++ // zero cuz write-only, or eof() to match basic_filebuf ++ VERIFY( strmof_1 == -1 ); + } + + int main() +--- libstdc++-v3/testsuite/27_io/basic_stringbuf/in_avail/char/21955.cc.jj 2005-07-22 01:22:04.000000000 +0200 ++++ libstdc++-v3/testsuite/27_io/basic_stringbuf/in_avail/char/21955.cc 2005-07-22 01:22:04.000000000 +0200 +@@ -0,0 +1,54 @@ ++// 2005-06-07 Benjamin Kosnik ++ ++// Copyright (C) 2005 ++// Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 2, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING. If not, write to the Free ++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++// USA. ++ ++#include ++#include ++#include ++ ++double ++test_stringstream() ++{ ++ double result; ++ char* source = "1918"; ++ std::stringstream s; ++ s << source; ++ ++ std::string tmp = s.str(); ++ std::streambuf* sb = s.rdbuf(); ++ int i = sb->in_avail(); ++ ++ if (i) ++ { ++ s >> result; ++ } ++ else ++ { ++ throw std::runtime_error("conversion failed"); ++ } ++ return result; ++} ++ ++ ++int main () ++{ ++ test_stringstream(); ++ return 0; ++} +--- libstdc++-v3/testsuite/27_io/basic_streambuf/in_avail/char/1.cc.jj 2005-07-22 01:21:41.000000000 +0200 ++++ libstdc++-v3/testsuite/27_io/basic_streambuf/in_avail/char/1.cc 2005-07-22 01:21:41.000000000 +0200 +@@ -0,0 +1,54 @@ ++// 2005-06-07 Benjamin Kosnik ++ ++// Copyright (C) 2005 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 2, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING. If not, write to the Free ++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++// USA. ++ ++// 27.8.1.4 Overridden virtual functions ++ ++#include ++#include ++ ++typedef std::basic_streambuf streambuf_type; ++ ++struct testbuf : streambuf_type ++{ ++ testbuf() { } ++}; ++ ++void test05() ++{ ++ typedef streambuf_type::int_type int_type; ++ typedef streambuf_type::traits_type traits_type; ++ typedef streambuf_type::pos_type pos_type; ++ typedef streambuf_type::off_type off_type; ++ typedef size_t size_type; ++ ++ bool test __attribute__((unused)) = true; ++ std::streamoff strmof_1, strmof_2; ++ testbuf sb01; ++ ++ // int in_avail() ++ strmof_1 = sb01.in_avail(); ++ VERIFY( strmof_1 == 0 ); ++} ++ ++int main() ++{ ++ test05(); ++ return 0; ++} +--- libstdc++-v3/testsuite/27_io/basic_streambuf/in_avail/wchar_t/1.cc.jj 2005-07-22 01:21:41.000000000 +0200 ++++ libstdc++-v3/testsuite/27_io/basic_streambuf/in_avail/wchar_t/1.cc 2005-07-22 01:21:41.000000000 +0200 +@@ -0,0 +1,54 @@ ++// 2005-06-07 Benjamin Kosnik ++ ++// Copyright (C) 2005 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 2, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING. If not, write to the Free ++// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++// USA. ++ ++// 27.8.1.4 Overridden virtual functions ++ ++#include ++#include ++ ++typedef std::basic_streambuf streambuf_type; ++ ++struct testbuf : streambuf_type ++{ ++ testbuf() { } ++}; ++ ++void test05() ++{ ++ typedef streambuf_type::int_type int_type; ++ typedef streambuf_type::traits_type traits_type; ++ typedef streambuf_type::pos_type pos_type; ++ typedef streambuf_type::off_type off_type; ++ typedef size_t size_type; ++ ++ bool test __attribute__((unused)) = true; ++ std::streamoff strmof_1, strmof_2; ++ testbuf sb01; ++ ++ // int in_avail() ++ strmof_1 = sb01.in_avail(); ++ VERIFY( strmof_1 == 0 ); ++} ++ ++int main() ++{ ++ test05(); ++ return 0; ++} +--- libstdc++-v3/testsuite/lib/libstdc++.exp.jj 2005-05-06 12:59:10.000000000 +0200 ++++ libstdc++-v3/testsuite/lib/libstdc++.exp 2005-07-22 10:03:52.000000000 +0200 +@@ -283,6 +283,7 @@ proc v3_target_compile { source dest typ + # Link the support objects into executables. + if { $type == "executable" } { + set cxx_final [concat $cxx_final ${v3-test_objs}] ++ lappend options "libs=-lstdc++_nonshared" + } + + lappend options "compiler=$cxx_final" diff --git a/SOURCES/gcc34-pr23591.patch b/SOURCES/gcc34-pr23591.patch new file mode 100644 index 0000000..335e7db --- /dev/null +++ b/SOURCES/gcc34-pr23591.patch @@ -0,0 +1,40 @@ +2006-01-10 Benjamin Kosnik + Ulrich Drepper + + PR libstdc++/23591 + * libsupc++/eh_globals.cc: Make global thread local. + +--- libstdc++-v3/libsupc++/eh_globals.cc.jj 2005-11-21 14:43:32.000000000 +0100 ++++ libstdc++-v3/libsupc++/eh_globals.cc 2006-04-21 15:38:55.000000000 +0200 +@@ -36,6 +36,26 @@ + + using namespace __cxxabiv1; + ++#if 1 ++namespace __gnu_internal ++{ ++ __cxxabiv1::__cxa_eh_globals* ++ get_global() throw() ++ { ++ static __thread __cxxabiv1::__cxa_eh_globals global __attribute__((tls_model ("initial-exec"))); ++ return &global; ++ } ++} ++ ++extern "C" __cxa_eh_globals* ++__cxxabiv1::__cxa_get_globals_fast() throw() ++{ return __gnu_internal::get_global(); } ++ ++extern "C" __cxa_eh_globals* ++__cxxabiv1::__cxa_get_globals() throw() ++{ return __gnu_internal::get_global(); } ++ ++#else + + // Single-threaded fallback buffer. + static __cxa_eh_globals globals_static; +@@ -125,3 +145,4 @@ __cxa_get_globals () throw() + return &globals_static; + #endif + } ++#endif diff --git a/SOURCES/gcc34-pr24975.patch b/SOURCES/gcc34-pr24975.patch new file mode 100644 index 0000000..ea9eb82 --- /dev/null +++ b/SOURCES/gcc34-pr24975.patch @@ -0,0 +1,361 @@ +2005-11-23 Paolo Carlini + + PR libstdc++/24975 (basic_string) + * include/bits/basic_string.h (_Rep::_S_empty_rep): Avoid + strict-aliasing warnings. + +2005-11-22 Paolo Carlini + + PR libstdc++/24975 + * include/bits/stl_set.h (insert(iterator, const value_type&), + erase(iterator), erase(iterator, iterator)): Don't break aliasing + rules casting to _Rep_iterator&, forward to _Rb_tree facilities. + * include/bits/stl_multiset.h (insert(iterator, const value_type&), + erase(iterator), erase(iterator, iterator)): Likewise. + * include/bits/stl_tree.h (_Rb_tree<>::_M_insert(_Const_Base_ptr, + _Const_Base_ptr, const value_type&), insert_unique(const_iterator, + const value_type&), insert_equal(const_iterator, const value_type&), + erase(const_iterator), erase(const_iterator, const_iterator)): New, + _Rb_tree<>::const_iterator counterparts of existing facilities. + +--- libstdc++-v3/include/bits/basic_string.h.jj 2007-02-23 21:29:15.000000000 +0100 ++++ libstdc++-v3/include/bits/basic_string.h 2007-07-19 12:11:40.000000000 +0200 +@@ -175,7 +175,16 @@ namespace std + + static _Rep& + _S_empty_rep() +- { return *reinterpret_cast<_Rep*>(&_S_empty_rep_storage); } ++ { ++#if __GNUC__ >= 4 ++ // Work around type-punning warning in g++4. _S_empty_rep_storage ++ // is never modified, so type-punning is ok. ++ void* __p = reinterpret_cast(&_S_empty_rep_storage); ++ return *reinterpret_cast<_Rep*>(__p); ++#else ++ return *reinterpret_cast<_Rep*>(&_S_empty_rep_storage); ++#endif ++ } + + bool + _M_is_leaked() const +--- libstdc++-v3/include/bits/stl_tree.h.jj 2007-02-23 21:29:15.000000000 +0100 ++++ libstdc++-v3/include/bits/stl_tree.h 2007-07-19 13:18:28.000000000 +0200 +@@ -532,6 +532,12 @@ namespace std + iterator + _M_insert(_Base_ptr __x, _Base_ptr __y, const value_type& __v); + ++#if __GNUC__ >= 4 ++ const_iterator ++ _M_insert(_Const_Base_ptr __x, _Const_Base_ptr __y, ++ const value_type& __v); ++#endif ++ + _Link_type + _M_copy(_Const_Link_type __x, _Link_type __p); + +@@ -631,9 +637,19 @@ namespace std + iterator + insert_unique(iterator __position, const value_type& __x); + ++#if __GNUC__ >= 4 ++ const_iterator ++ insert_unique(const_iterator __position, const value_type& __x); ++#endif ++ + iterator + insert_equal(iterator __position, const value_type& __x); + ++#if __GNUC__ >= 4 ++ const_iterator ++ insert_equal(const_iterator __position, const value_type& __x); ++#endif ++ + template + void + insert_unique(_InputIterator __first, _InputIterator __last); +@@ -645,12 +661,22 @@ namespace std + void + erase(iterator __position); + ++#if __GNUC__ >= 4 ++ void ++ erase(const_iterator __position); ++#endif ++ + size_type + erase(const key_type& __x); + + void + erase(iterator __first, iterator __last); + ++#if __GNUC__ >= 4 ++ void ++ erase(const_iterator __first, const_iterator __last); ++#endif ++ + void + erase(const key_type* __first, const key_type* __last); + +@@ -793,6 +819,28 @@ namespace std + return iterator(__z); + } + ++#if __GNUC__ >= 4 ++ template ++ typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::const_iterator ++ _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: ++ _M_insert(_Const_Base_ptr __x, _Const_Base_ptr __p, const _Val& __v) ++ { ++ _Link_type __z = _M_create_node(__v); ++ bool __insert_left; ++ ++ __insert_left = __x != 0 || __p == _M_end() ++ || _M_impl._M_key_compare(_KeyOfValue()(__v), ++ _S_key(__p)); ++ ++ _Rb_tree_insert_and_rebalance(__insert_left, __z, ++ const_cast<_Base_ptr>(__p), ++ this->_M_impl._M_header); ++ ++_M_impl._M_node_count; ++ return const_iterator(__z); ++ } ++#endif ++ + template + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator +@@ -928,6 +976,54 @@ namespace std + } + } + ++#if __GNUC__ >= 4 ++ template ++ typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator ++ _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: ++ insert_unique(const_iterator __position, const _Val& __v) ++ { ++ if (__position._M_node == _M_leftmost()) ++ { ++ // begin() ++ if (size() > 0 ++ && _M_impl._M_key_compare(_KeyOfValue()(__v), ++ _S_key(__position._M_node))) ++ return _M_insert(__position._M_node, __position._M_node, __v); ++ // First argument just needs to be non-null. ++ else ++ return const_iterator(insert_unique(__v).first); ++ } ++ else if (__position._M_node == _M_end()) ++ { ++ // end() ++ if (_M_impl._M_key_compare(_S_key(_M_rightmost()), ++ _KeyOfValue()(__v))) ++ return _M_insert(0, _M_rightmost(), __v); ++ else ++ return const_iterator(insert_unique(__v).first); ++ } ++ else ++ { ++ const_iterator __before = __position; ++ --__before; ++ if (_M_impl._M_key_compare(_S_key(__before._M_node), ++ _KeyOfValue()(__v)) ++ && _M_impl._M_key_compare(_KeyOfValue()(__v), ++ _S_key(__position._M_node))) ++ { ++ if (_S_right(__before._M_node) == 0) ++ return _M_insert(0, __before._M_node, __v); ++ else ++ return _M_insert(__position._M_node, __position._M_node, __v); ++ // First argument just needs to be non-null. ++ } ++ else ++ return const_iterator(insert_unique(__v).first); ++ } ++ } ++#endif ++ + template + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator +@@ -974,6 +1070,54 @@ namespace std + } + } + ++#if __GNUC__ >= 4 ++ template ++ typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::const_iterator ++ _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: ++ insert_equal(const_iterator __position, const _Val& __v) ++ { ++ if (__position._M_node == _M_leftmost()) ++ { ++ // begin() ++ if (size() > 0 ++ && !_M_impl._M_key_compare(_S_key(__position._M_node), ++ _KeyOfValue()(__v))) ++ return _M_insert(__position._M_node, __position._M_node, __v); ++ // first argument just needs to be non-null ++ else ++ return const_iterator(insert_equal(__v)); ++ } ++ else if (__position._M_node == _M_end()) ++ { ++ // end() ++ if (!_M_impl._M_key_compare(_KeyOfValue()(__v), ++ _S_key(_M_rightmost()))) ++ return _M_insert(0, _M_rightmost(), __v); ++ else ++ return const_iterator(insert_equal(__v)); ++ } ++ else ++ { ++ const_iterator __before = __position; ++ --__before; ++ if (!_M_impl._M_key_compare(_KeyOfValue()(__v), ++ _S_key(__before._M_node)) ++ && !_M_impl._M_key_compare(_S_key(__position._M_node), ++ _KeyOfValue()(__v))) ++ { ++ if (_S_right(__before._M_node) == 0) ++ return _M_insert(0, __before._M_node, __v); ++ else ++ return _M_insert(__position._M_node, __position._M_node, __v); ++ // First argument just needs to be non-null. ++ } ++ else ++ return const_iterator(insert_equal(__v)); ++ } ++ } ++#endif ++ + template + template +@@ -1008,6 +1152,20 @@ namespace std + --_M_impl._M_node_count; + } + ++#if __GNUC__ >= 4 ++ template ++ inline void ++ _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::erase(const_iterator __position) ++ { ++ _Link_type __y = ++ static_cast<_Link_type>(_Rb_tree_rebalance_for_erase(const_cast<_Base_ptr>(__position._M_node), ++ this->_M_impl._M_header)); ++ destroy_node(__y); ++ --_M_impl._M_node_count; ++ } ++#endif ++ + template + typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::size_type +@@ -1082,6 +1240,20 @@ namespace std + while (__first != __last) erase(__first++); + } + ++#if __GNUC__ >= 4 ++ template ++ void ++ _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>:: ++ erase(const_iterator __first, const_iterator __last) ++ { ++ if (__first == begin() && __last == end()) ++ clear(); ++ else ++ while (__first != __last) erase(__first++); ++ } ++#endif ++ + template + void +--- libstdc++-v3/include/bits/stl_multiset.h.jj 2007-02-23 21:29:15.000000000 +0100 ++++ libstdc++-v3/include/bits/stl_multiset.h 2007-07-19 12:30:47.000000000 +0200 +@@ -328,8 +328,12 @@ namespace _GLIBCXX_STD + iterator + insert(iterator __position, const value_type& __x) + { ++#if __GNUC__ >= 4 ++ return _M_t.insert_equal(__position, __x); ++#else + typedef typename _Rep_type::iterator _Rep_iterator; + return _M_t.insert_equal((_Rep_iterator&)__position, __x); ++#endif + } + + /** +@@ -358,8 +362,12 @@ namespace _GLIBCXX_STD + void + erase(iterator __position) + { ++#if __GNUC__ >= 4 ++ _M_t.erase(__position); ++#else + typedef typename _Rep_type::iterator _Rep_iterator; + _M_t.erase((_Rep_iterator&)__position); ++#endif + } + + /** +@@ -391,8 +399,12 @@ namespace _GLIBCXX_STD + void + erase(iterator __first, iterator __last) + { ++#if __GNUC__ >= 4 ++ _M_t.erase(__first, __last); ++#else + typedef typename _Rep_type::iterator _Rep_iterator; + _M_t.erase((_Rep_iterator&)__first, (_Rep_iterator&)__last); ++#endif + } + + /** +--- libstdc++-v3/include/bits/stl_set.h.jj 2007-02-23 21:29:15.000000000 +0100 ++++ libstdc++-v3/include/bits/stl_set.h 2007-07-19 12:23:57.000000000 +0200 +@@ -337,8 +337,12 @@ namespace _GLIBCXX_STD + iterator + insert(iterator __position, const value_type& __x) + { ++#if __GNUC__ >= 4 ++ return _M_t.insert_unique(__position, __x); ++#else + typedef typename _Rep_type::iterator _Rep_iterator; + return _M_t.insert_unique((_Rep_iterator&)__position, __x); ++#endif + } + + /** +@@ -366,8 +370,12 @@ namespace _GLIBCXX_STD + void + erase(iterator __position) + { ++#if __GNUC__ >= 4 ++ _M_t.erase(__position); ++#else + typedef typename _Rep_type::iterator _Rep_iterator; + _M_t.erase((_Rep_iterator&)__position); ++#endif + } + + /** +@@ -398,8 +406,12 @@ namespace _GLIBCXX_STD + void + erase(iterator __first, iterator __last) + { ++#if __GNUC__ >= 4 ++ _M_t.erase(__first, __last); ++#else + typedef typename _Rep_type::iterator _Rep_iterator; + _M_t.erase((_Rep_iterator&)__first, (_Rep_iterator&)__last); ++#endif + } + + /** diff --git a/SOURCES/gcc34-pr26208-workaround.patch b/SOURCES/gcc34-pr26208-workaround.patch new file mode 100644 index 0000000..b832494 --- /dev/null +++ b/SOURCES/gcc34-pr26208-workaround.patch @@ -0,0 +1,199 @@ +--- gcc/unwind-dw2.c.jj 2006-05-22 13:39:48.000000000 -0400 ++++ gcc/unwind-dw2.c 2006-05-22 13:48:20.000000000 -0400 +@@ -40,6 +40,7 @@ + #include "unwind-pe.h" + #include "unwind-dw2-fde.h" + #include "gthr.h" ++#include + + + #ifndef __USING_SJLJ_EXCEPTIONS__ +@@ -81,8 +82,15 @@ struct _Unwind_Context + void *ra; + void *lsda; + struct dwarf_eh_bases bases; +- _Unwind_Word args_size; +- char signal_frame; ++#if __BYTE_ORDER == __BIG_ENDIAN ++ _Unwind_Word signal_frame : 1; ++ _Unwind_Word args_size : sizeof (_Unwind_Word) * 8 - 1; ++#elif __BYTE_ORDER == __LITTLE_ENDIAN ++ _Unwind_Word args_size : sizeof (_Unwind_Word) * 8 - 1; ++ _Unwind_Word signal_frame : 1; ++#else ++#error Unknown endianity ++#endif + }; + + /* Byte size of every register managed by these routines. */ +@@ -1003,7 +1011,13 @@ execute_cfa_program (const unsigned char + break; + + case DW_CFA_GNU_args_size: +- insn_ptr = read_uleb128 (insn_ptr, &context->args_size); ++ { ++ _Unwind_Word args_size; ++ insn_ptr = read_uleb128 (insn_ptr, &args_size); ++ context->args_size = args_size; ++ if (context->args_size != args_size) ++ abort (); ++ } + break; + + case DW_CFA_GNU_negative_offset_extended: +--- libjava/exception.cc.jj 2006-05-22 13:39:48.000000000 -0400 ++++ libjava/exception.cc 2006-05-22 14:48:30.000000000 -0400 +@@ -31,6 +31,153 @@ namespace std + } + #include "unwind.h" + ++#if defined PIC && !defined __ia64__ ++ ++#include ++ ++extern "C" { ++ ++static void *libgcc_s_handle; ++ ++_Unwind_Reason_Code __attribute__((visibility ("hidden"))) ++_Unwind_RaiseException (struct _Unwind_Exception *exc) ++{ ++ static _Unwind_Reason_Code (*RaiseException) (struct _Unwind_Exception *); ++ ++ if (RaiseException == NULL) ++ { ++ if (libgcc_s_handle == NULL) ++ libgcc_s_handle = dlopen ("libgcc_s.so.1", RTLD_LAZY); ++ RaiseException = (__typeof (RaiseException)) ++ dlsym (libgcc_s_handle, "_Unwind_RaiseException"); ++ } ++ return RaiseException (exc); ++} ++ ++void __attribute__((visibility ("hidden"))) ++_Unwind_Resume (struct _Unwind_Exception *exc) ++{ ++ static void (*Resume) (struct _Unwind_Exception *); ++ ++ if (Resume == NULL) ++ { ++ if (libgcc_s_handle == NULL) ++ libgcc_s_handle = dlopen ("libgcc_s.so.1", RTLD_LAZY); ++ Resume = (__typeof (Resume)) ++ dlsym (libgcc_s_handle, "_Unwind_Resume"); ++ } ++ Resume (exc); ++} ++ ++__attribute__((visibility ("hidden"))) void * ++_Unwind_GetLanguageSpecificData (struct _Unwind_Context *ctx) ++{ ++ static void * (*GetLanguageSpecificData) (struct _Unwind_Context *); ++ ++ if (GetLanguageSpecificData == NULL) ++ { ++ if (libgcc_s_handle == NULL) ++ libgcc_s_handle = dlopen ("libgcc_s.so.1", RTLD_LAZY); ++ GetLanguageSpecificData = (__typeof (GetLanguageSpecificData)) ++ dlsym (libgcc_s_handle, "_Unwind_GetLanguageSpecificData"); ++ } ++ return GetLanguageSpecificData (ctx); ++} ++ ++_Unwind_Ptr __attribute__((visibility ("hidden"))) ++_Unwind_GetRegionStart (struct _Unwind_Context *ctx) ++{ ++ static _Unwind_Ptr (*GetRegionStart) (struct _Unwind_Context *); ++ ++ if (GetRegionStart == NULL) ++ { ++ if (libgcc_s_handle == NULL) ++ libgcc_s_handle = dlopen ("libgcc_s.so.1", RTLD_LAZY); ++ GetRegionStart = (__typeof (GetRegionStart)) ++ dlsym (libgcc_s_handle, "_Unwind_GetRegionStart"); ++ } ++ return GetRegionStart (ctx); ++} ++ ++_Unwind_Ptr __attribute__((visibility ("hidden"))) ++_Unwind_GetDataRelBase (struct _Unwind_Context *ctx) ++{ ++ static _Unwind_Ptr (*GetDataRelBase) (struct _Unwind_Context *); ++ ++ if (GetDataRelBase == NULL) ++ { ++ if (libgcc_s_handle == NULL) ++ libgcc_s_handle = dlopen ("libgcc_s.so.1", RTLD_LAZY); ++ GetDataRelBase = (__typeof (GetDataRelBase)) ++ dlsym (libgcc_s_handle, "_Unwind_GetDataRelBase"); ++ } ++ return GetDataRelBase (ctx); ++} ++ ++_Unwind_Ptr __attribute__((visibility ("hidden"))) ++_Unwind_GetTextRelBase (struct _Unwind_Context *ctx) ++{ ++ static _Unwind_Ptr (*GetTextRelBase) (struct _Unwind_Context *); ++ ++ if (GetTextRelBase == NULL) ++ { ++ if (libgcc_s_handle == NULL) ++ libgcc_s_handle = dlopen ("libgcc_s.so.1", RTLD_LAZY); ++ GetTextRelBase = (__typeof (GetTextRelBase)) ++ dlsym (libgcc_s_handle, "_Unwind_GetTextRelBase"); ++ } ++ return GetTextRelBase (ctx); ++} ++ ++_Unwind_Ptr __attribute__((visibility ("hidden"))) ++_Unwind_GetIPInfo (struct _Unwind_Context *ctx, int *ip) ++{ ++ static _Unwind_Ptr (*GetIPInfo) (struct _Unwind_Context *, int *ip); ++ ++ if (GetIPInfo == NULL) ++ { ++ if (libgcc_s_handle == NULL) ++ libgcc_s_handle = dlopen ("libgcc_s.so.1", RTLD_LAZY); ++ GetIPInfo = (__typeof (GetIPInfo)) ++ dlsym (libgcc_s_handle, "_Unwind_GetIPInfo"); ++ } ++ return GetIPInfo (ctx, ip); ++} ++ ++void __attribute__((visibility ("hidden"))) ++_Unwind_SetIP (struct _Unwind_Context *ctx, _Unwind_Ptr ip) ++{ ++ static void (*SetIP) (struct _Unwind_Context *, _Unwind_Ptr ip); ++ ++ if (SetIP == NULL) ++ { ++ if (libgcc_s_handle == NULL) ++ libgcc_s_handle = dlopen ("libgcc_s.so.1", RTLD_LAZY); ++ SetIP = (__typeof (SetIP)) ++ dlsym (libgcc_s_handle, "_Unwind_SetIP"); ++ } ++ SetIP (ctx, ip); ++} ++ ++void __attribute__((visibility ("hidden"))) ++_Unwind_SetGR (struct _Unwind_Context *ctx, int num, _Unwind_Ptr gr) ++{ ++ static void (*SetGR) (struct _Unwind_Context *, int num, _Unwind_Ptr gr); ++ ++ if (SetGR == NULL) ++ { ++ if (libgcc_s_handle == NULL) ++ libgcc_s_handle = dlopen ("libgcc_s.so.1", RTLD_LAZY); ++ SetGR = (__typeof (SetGR)) ++ dlsym (libgcc_s_handle, "_Unwind_SetGR"); ++ } ++ SetGR (ctx, num, gr); ++} ++ ++} ++ ++#endif ++ + struct alignment_test_struct + { + char space; diff --git a/SOURCES/gcc34-pr26208.patch b/SOURCES/gcc34-pr26208.patch new file mode 100644 index 0000000..f4d0ecd --- /dev/null +++ b/SOURCES/gcc34-pr26208.patch @@ -0,0 +1,431 @@ +2006-02-27 Jakub Jelinek + + PR other/26208 + * unwind-dw2.c (struct _Unwind_Context): Add signal_frame field. + (_Unwind_FrameState): Add signal_frame field. + (extract_cie_info): Handle S flag in augmentation string. + (execute_cfa_program): If context->signal_frame, execute also + fs->pc == context->ra instructions. + (uw_frame_state_for): If context->signal_frame, don't subtract one + from context->ra to find FDE. + (uw_update_context_1): Set context->signal_frame to + fs->signal_frame. + (_Unwind_GetIPInfo): New function. + * unwind-c.c (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead + of _Unwind_GetIP. + * unwind-sjlj.c (_Unwind_GetIPInfo): New function. + * unwind.h (_Unwind_GetIPInfo): New prototype. + * unwind-compat.c (_Unwind_GetIPInfo): New function. + * libgcc-std.ver (_Unwind_GetIPInfo): Export @@GCC_4.2.0. + * config/ia64/unwind-ia64.c (_Unwind_GetIPInfo): New function. + * config/i386/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Set + (FS)->signal_frame. + * config/i386/linux64.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise. + * config/rs6000/linux-unwind.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise. + * config/s390/linux.h (MD_FALLBACK_FRAME_STATE_FOR): Likewise. + + * libsupc++/eh_personality.cc (PERSONALITY_FUNCTION): Use + _Unwind_GetIPInfo instead of _Unwind_GetIP. + + * exception.cc (PERSONALITY_FUNCTION): Use _Unwind_GetIPInfo instead + of _Unwind_GetIP. + * include/i386-signal.h (MAKE_THROW_FRAME): Change into empty macro. + (HANDLE_DIVIDE_OVERFLOW): Don't adjust _res->eip if falling through + to throw. + * include/x86_64-signal.h (MAKE_THROW_FRAME): Change into empty + macro. + * include/powerpc-signal.h (MAKE_THROW_FRAME): Change into empty + macro. + +--- libjava/exception.cc.jj 2005-11-21 14:47:25.000000000 +0100 ++++ libjava/exception.cc 2006-04-21 14:00:19.000000000 +0200 +@@ -199,6 +199,7 @@ PERSONALITY_FUNCTION (int version, + int handler_switch_value; + bool saw_cleanup; + bool saw_handler; ++ int ip_before_insn = 0; + + + // Interface version check. +@@ -214,10 +215,10 @@ PERSONALITY_FUNCTION (int version, + goto install_context; + } + +- // FIXME: In Phase 1, record _Unwind_GetIP in xh->obj as a part of ++ // FIXME: In Phase 1, record _Unwind_GetIPInfo in xh->obj as a part of + // the stack trace for this exception. This will only collect Java + // frames, but perhaps that is acceptable. +- // FIXME2: _Unwind_GetIP is nonsensical for SJLJ, being a call-site ++ // FIXME2: _Unwind_GetIPInfo is nonsensical for SJLJ, being a call-site + // index instead of a PC value. We could perhaps arrange for + // _Unwind_GetRegionStart to return context->fc->jbuf[1], which + // is the address of the handler label for __builtin_longjmp, but +@@ -232,7 +233,9 @@ PERSONALITY_FUNCTION (int version, + + // Parse the LSDA header. + p = parse_lsda_header (context, language_specific_data, &info); +- ip = _Unwind_GetIP (context) - 1; ++ ip = _Unwind_GetIPInfo (context, &ip_before_insn); ++ if (! ip_before_insn) ++ --ip; + landing_pad = 0; + action_record = 0; + handler_switch_value = 0; +--- libjava/include/i386-signal.h.jj 2005-11-21 14:47:15.000000000 +0100 ++++ libjava/include/i386-signal.h 2006-04-21 14:57:55.000000000 +0200 +@@ -22,19 +22,7 @@ details. */ + #define SIGNAL_HANDLER(_name) \ + static void _name (int _dummy) + +-#define MAKE_THROW_FRAME(_exception) \ +-do \ +-{ \ +- void **_p = (void **)&_dummy; \ +- struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p; \ +- \ +- /* Advance the program counter so that it is after the start of the \ +- instruction: the x86 exception handler expects \ +- the PC to point to the instruction after a call. */ \ +- _regs->eip += 2; \ +- \ +-} \ +-while (0) ++#define MAKE_THROW_FRAME(_exception) + + #define HANDLE_DIVIDE_OVERFLOW \ + do \ +@@ -84,14 +72,6 @@ do \ + _regs->eip = (unsigned long)_eip; \ + return; \ + } \ +- else \ +- { \ +- /* Advance the program counter so that it is after the start \ +- of the instruction: this is because the x86 exception \ +- handler expects the PC to point to the instruction after a \ +- call. */ \ +- _regs->eip += 2; \ +- } \ + } \ + } \ + while (0) +--- libjava/include/x86_64-signal.h.jj 2006-04-20 17:02:27.000000000 +0200 ++++ libjava/include/x86_64-signal.h 2006-04-21 14:00:19.000000000 +0200 +@@ -34,17 +34,7 @@ extern "C" + }; + } + +-#define MAKE_THROW_FRAME(_exception) \ +-do \ +-{ \ +- /* Advance the program counter so that it is after the start of the \ +- instruction: the x86_64 exception handler expects \ +- the PC to point to the instruction after a call. */ \ +- struct ucontext *_uc = (struct ucontext *)_p; \ +- volatile struct sigcontext *_sc = (struct sigcontext *) &_uc->uc_mcontext; \ +- _sc->rip += 2; \ +-} \ +-while (0) ++#define MAKE_THROW_FRAME(_exception) + + #define RESTORE(name, syscall) RESTORE2 (name, syscall) + #define RESTORE2(name, syscall) \ +--- libjava/include/powerpc-signal.h.jj 2005-11-21 14:47:15.000000000 +0100 ++++ libjava/include/powerpc-signal.h 2006-04-21 14:00:19.000000000 +0200 +@@ -22,18 +22,12 @@ details. */ + #define SIGNAL_HANDLER(_name) \ + static void _name (int /* _signal */, struct sigcontext *_sc) + +-/* PPC either leaves PC pointing at a faulting instruction or the +- following instruction, depending on the signal. SEGV always does +- the former, so we adjust the saved PC to point to the following +- instruction. This is what the handler in libgcc expects. */ ++/* MD_FALBACK_FRAME_STATE_FOR takes care of special casing PC ++ before the faulting instruction, so we don't need to do anything ++ here. */ ++ ++#define MAKE_THROW_FRAME(_exception) + +-#define MAKE_THROW_FRAME(_exception) \ +-do \ +- { \ +- _sc->regs->nip += 4; \ +- } \ +-while (0) +- + /* For an explanation why we cannot simply use sigaction to + install the handlers, see i386-signal.h. */ + +--- libstdc++-v3/libsupc++/eh_personality.cc.jj 2005-11-21 14:43:32.000000000 +0100 ++++ libstdc++-v3/libsupc++/eh_personality.cc 2006-04-21 14:24:34.000000000 +0200 +@@ -201,6 +201,7 @@ PERSONALITY_FUNCTION (int version, + _Unwind_Ptr landing_pad, ip; + int handler_switch_value; + void *thrown_ptr = xh + 1; ++ int ip_before_insn = 0; + + // Interface version check. + if (version != 1) +@@ -227,7 +228,9 @@ PERSONALITY_FUNCTION (int version, + // Parse the LSDA header. + p = parse_lsda_header (context, language_specific_data, &info); + info.ttype_base = base_of_encoded_value (info.ttype_encoding, context); +- ip = _Unwind_GetIP (context) - 1; ++ ip = _Unwind_GetIPInfo (context, &ip_before_insn); ++ if (! ip_before_insn) ++ --ip; + landing_pad = 0; + action_record = 0; + handler_switch_value = 0; +--- gcc/libgcc-std.ver.jj 2005-11-21 14:43:21.000000000 +0100 ++++ gcc/libgcc-std.ver 2006-04-21 14:02:13.000000000 +0200 +@@ -234,3 +234,8 @@ GCC_3.4.4 { + __negvti2 + __subvti3 + } ++ ++%inherit GCC_4.2.0 GCC_3.4.4 ++GCC_4.2.0 { ++ _Unwind_GetIPInfo ++} +--- gcc/unwind-c.c.jj 2005-11-21 14:43:20.000000000 +0100 ++++ gcc/unwind-c.c 2006-04-21 14:00:08.000000000 +0200 +@@ -102,6 +102,7 @@ PERSONALITY_FUNCTION (int version, + lsda_header_info info; + const unsigned char *language_specific_data, *p, *action_record; + _Unwind_Ptr landing_pad, ip; ++ int ip_before_insn = 0; + + if (version != 1) + return _URC_FATAL_PHASE1_ERROR; +@@ -119,7 +120,9 @@ PERSONALITY_FUNCTION (int version, + + /* Parse the LSDA header. */ + p = parse_lsda_header (context, language_specific_data, &info); +- ip = _Unwind_GetIP (context) - 1; ++ ip = _Unwind_GetIPInfo (context, &ip_before_insn); ++ if (! ip_before_insn) ++ --ip; + landing_pad = 0; + + #ifdef __USING_SJLJ_EXCEPTIONS__ +--- gcc/config/rs6000/linux-unwind.h.jj 2005-11-21 14:41:11.000000000 +0100 ++++ gcc/config/rs6000/linux-unwind.h 2006-04-21 14:23:09.000000000 +0200 +@@ -247,6 +247,7 @@ enum { SIGNAL_FRAMESIZE = 64 }; + (FS)->regs.reg[ARG_POINTER_REGNUM].loc.offset \ + = (long) ®s->nip - new_cfa; \ + (FS)->retaddr_column = ARG_POINTER_REGNUM; \ ++ (FS)->signal_frame = 1; \ + \ + if (hwcap == 0) \ + { \ +--- gcc/config/s390/linux.h.jj 2005-11-21 14:40:55.000000000 +0100 ++++ gcc/config/s390/linux.h 2006-04-21 14:15:46.000000000 +0200 +@@ -113,6 +113,7 @@ Software Foundation, 59 Temple Place - S + } __attribute__ ((__aligned__ (8))) sigregs_; \ + \ + sigregs_ *regs_; \ ++ int *signo_ = NULL; \ + \ + /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn */ \ + if (pc_[0] != 0x0a || (pc_[1] != 119 && pc_[1] != 173)) \ +@@ -133,6 +134,7 @@ Software Foundation, 59 Temple Place - S + } *uc_ = (CONTEXT)->cfa + 8 + 128; \ + \ + regs_ = &uc_->uc_mcontext; \ ++ signo_ = (CONTEXT)->cfa + sizeof(long); \ + } \ + \ + /* Old-style RT frame and all non-RT frames: \ +@@ -141,6 +143,11 @@ Software Foundation, 59 Temple Place - S + else \ + { \ + regs_ = *(sigregs_ **)((CONTEXT)->cfa + 8); \ ++ /* Recent kernels store the signal number immediately after \ ++ the sigregs; old kernels have the return trampoline at \ ++ this location. */ \ ++ if ((void *)(regs_ + 1) != (CONTEXT)->ra) \ ++ signo_ = (int *)(regs_ + 1); \ + } \ + \ + new_cfa_ = regs_->gprs[15] + 16*sizeof(long) + 32; \ +@@ -167,6 +174,12 @@ Software Foundation, 59 Temple Place - S + (FS)->regs.reg[32].loc.offset = (long)®s_->psw_addr - new_cfa_; \ + (FS)->retaddr_column = 32; \ + \ ++ /* SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr \ ++ after the faulting instruction rather than before it. \ ++ Don't set FS->signal_frame in that case. */ \ ++ if (!signo_ || (*signo_ != 4 && *signo_ != 5 && *signo_ != 8)) \ ++ (FS)->signal_frame = 1; \ ++ \ + goto SUCCESS; \ + } while (0) + +--- gcc/config/i386/linux.h.jj 2005-11-21 14:41:07.000000000 +0100 ++++ gcc/config/i386/linux.h 2006-04-21 14:18:05.000000000 +0200 +@@ -268,6 +268,7 @@ Boston, MA 02111-1307, USA. */ + (FS)->regs.reg[8].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_; \ + (FS)->retaddr_column = 8; \ ++ (FS)->signal_frame = 1; \ + goto SUCCESS; \ + } while (0) + #endif /* not USE_GNULIBC_1 */ +--- gcc/config/i386/linux64.h.jj 2005-11-21 14:41:07.000000000 +0100 ++++ gcc/config/i386/linux64.h 2006-04-21 14:18:45.000000000 +0200 +@@ -136,6 +136,7 @@ Boston, MA 02111-1307, USA. */ + (FS)->regs.reg[16].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[16].loc.offset = (long)&sc_->rip - new_cfa_; \ + (FS)->retaddr_column = 16; \ ++ (FS)->signal_frame = 1; \ + goto SUCCESS; \ + } while (0) + #else /* ifdef __x86_64__ */ +@@ -190,6 +191,7 @@ Boston, MA 02111-1307, USA. */ + (FS)->regs.reg[8].how = REG_SAVED_OFFSET; \ + (FS)->regs.reg[8].loc.offset = (long)&sc_->eip - new_cfa_; \ + (FS)->retaddr_column = 8; \ ++ (FS)->signal_frame = 1; \ + goto SUCCESS; \ + } while (0) + #endif /* ifdef __x86_64__ */ +--- gcc/config/ia64/unwind-ia64.c.jj 2005-11-21 14:40:57.000000000 +0100 ++++ gcc/config/ia64/unwind-ia64.c 2006-04-21 14:00:11.000000000 +0200 +@@ -1748,6 +1748,13 @@ _Unwind_GetIP (struct _Unwind_Context *c + return context->rp; + } + ++inline _Unwind_Ptr ++_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) ++{ ++ *ip_before_insn = 0; ++ return context->rp; ++} ++ + /* Overwrite the return address for CONTEXT with VAL. */ + + inline void +--- gcc/unwind-compat.c.jj 2005-11-21 14:43:20.000000000 +0100 ++++ gcc/unwind-compat.c 2006-04-21 13:59:59.000000000 +0200 +@@ -134,6 +134,13 @@ _Unwind_GetIP (struct _Unwind_Context *c + } + symver (_Unwind_GetIP, GCC_3.0); + ++_Unwind_Ptr ++_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) ++{ ++ *ip_before_insn = 0; ++ return __libunwind_Unwind_GetIP (context); ++} ++ + extern void *__libunwind_Unwind_GetLanguageSpecificData + (struct _Unwind_Context *); + +--- gcc/unwind-sjlj.c.jj 2005-11-21 14:43:21.000000000 +0100 ++++ gcc/unwind-sjlj.c 2006-04-21 14:00:08.000000000 +0200 +@@ -202,6 +202,13 @@ _Unwind_GetIP (struct _Unwind_Context *c + return context->fc->call_site + 1; + } + ++_Unwind_Ptr ++_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) ++{ ++ *ip_before_insn = 0; ++ return context->fc->call_site + 1; ++} ++ + /* Set the return landing pad index in CONTEXT. */ + + void +--- gcc/unwind.h.jj 2005-11-21 14:43:20.000000000 +0100 ++++ gcc/unwind.h 2006-04-21 14:08:51.000000000 +0200 +@@ -151,6 +151,7 @@ extern _Unwind_Word _Unwind_GetGR (struc + extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word); + + extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *); ++extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *); + extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr); + + /* @@@ Retrieve the CFA of the given context. */ +--- gcc/unwind-dw2.c.jj 2005-11-21 14:43:21.000000000 +0100 ++++ gcc/unwind-dw2.c 2006-04-21 14:05:32.000000000 +0200 +@@ -82,6 +82,7 @@ struct _Unwind_Context + void *lsda; + struct dwarf_eh_bases bases; + _Unwind_Word args_size; ++ char signal_frame; + }; + + /* Byte size of every register managed by these routines. */ +@@ -137,6 +138,7 @@ typedef struct + unsigned char fde_encoding; + unsigned char lsda_encoding; + unsigned char saw_z; ++ unsigned char signal_frame; + void *eh_ptr; + } _Unwind_FrameState; + +@@ -271,6 +273,16 @@ _Unwind_GetIP (struct _Unwind_Context *c + return (_Unwind_Ptr) context->ra; + } + ++/* Retrieve the return address and flag whether that IP is before ++ or after first not yet fully executed instruction. */ ++ ++inline _Unwind_Ptr ++_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn) ++{ ++ *ip_before_insn = context->signal_frame != 0; ++ return (_Unwind_Ptr) context->ra; ++} ++ + /* Overwrite the return address for CONTEXT with VAL. */ + + inline void +@@ -382,6 +394,13 @@ extract_cie_info (const struct dwarf_cie + aug += 1; + } + ++ /* "S" indicates a signal frame. */ ++ else if (aug[0] == 'S') ++ { ++ fs->signal_frame = 1; ++ aug += 1; ++ } ++ + /* Otherwise we have an unknown augmentation string. + Bail unless we saw a 'z' prefix. */ + else +@@ -818,8 +837,10 @@ execute_cfa_program (const unsigned char + a different stack configuration that we are not interested in. We + assume that the call itself is unwind info-neutral; if not, or if + there are delay instructions that adjust the stack, these must be +- reflected at the point immediately before the call insn. */ +- while (insn_ptr < insn_end && fs->pc < context->ra) ++ reflected at the point immediately before the call insn. ++ In signal frames, return address is after last completed instruction, ++ so we add 1 to return address to make the comparison <=. */ ++ while (insn_ptr < insn_end && fs->pc < context->ra + context->signal_frame) + { + unsigned char insn = *insn_ptr++; + _Unwind_Word reg, utmp; +@@ -1021,7 +1042,8 @@ uw_frame_state_for (struct _Unwind_Conte + if (context->ra == 0) + return _URC_END_OF_STACK; + +- fde = _Unwind_Find_FDE (context->ra - 1, &context->bases); ++ fde = _Unwind_Find_FDE (context->ra + context->signal_frame - 1, ++ &context->bases); + if (fde == NULL) + { + /* Couldn't find frame unwind info for this function. Try a +@@ -1376,6 +1398,8 @@ uw_update_context_1 (struct _Unwind_Cont + break; + } + ++ context->signal_frame = fs->signal_frame; ++ + MD_FROB_UPDATE_CONTEXT (context, fs); + } + diff --git a/SOURCES/gcc34-pr56258.patch b/SOURCES/gcc34-pr56258.patch new file mode 100644 index 0000000..737b683 --- /dev/null +++ b/SOURCES/gcc34-pr56258.patch @@ -0,0 +1,107 @@ +2013-02-20 Jakub Jelinek + + PR bootstrap/56258 + * doc/invoke.texi: Fix errors reported by makeinfo 5.0. + * doc/md.texi: Likewise. + * doc/rtl.texi: Likewise. + * doc/extend.texi: Likewise. + * doc/cppopts.texi: Likewise. + * doc/c-tree.texi: Likewise. + +--- gcc/doc/invoke.texi.jj 2005-11-21 14:55:23.000000000 +0100 ++++ gcc/doc/invoke.texi 2013-02-20 16:51:51.906808675 +0100 +@@ -790,7 +790,7 @@ instantiation), or a library unit renami + generic, or subprogram renaming declaration). Such files are also + called @dfn{specs}. + +-@itemx @var{file}.adb ++@item @var{file}.adb + Ada source code file containing a library unit body (a subprogram or + package body). Such files are also called @dfn{bodies}. + +@@ -6679,7 +6679,7 @@ assembly code. Permissible names are: @ + @samp{arm1136js}, @samp{arm1136jfs} ,@samp{xscale}, @samp{iwmmxt}, + @samp{ep9312}. + +-@itemx -mtune=@var{name} ++@item -mtune=@var{name} + @opindex mtune + This option is very similar to the @option{-mcpu=} option, except that + instead of specifying the actual target processor type, and hence +@@ -7993,7 +7993,7 @@ floating-point calculations using librar + Assume that the floating-point coprocessor only supports single-precision + operations. + +-@itemx -mdouble-float ++@item -mdouble-float + @opindex mdouble-float + Assume that the floating-point coprocessor supports double-precision + operations. This is the default. +--- gcc/doc/md.texi.jj 2005-11-21 14:35:16.000000000 +0100 ++++ gcc/doc/md.texi 2013-02-20 17:02:33.425214891 +0100 +@@ -2539,9 +2539,10 @@ means of constraints requiring operands + @itemx @samp{smin@var{m}3}, @samp{smax@var{m}3}, @samp{umin@var{m}3}, @samp{umax@var{m}3} + @itemx @samp{and@var{m}3}, @samp{ior@var{m}3}, @samp{xor@var{m}3} + Similar, for other arithmetic operations. ++ + @cindex @code{min@var{m}3} instruction pattern + @cindex @code{max@var{m}3} instruction pattern +-@itemx @samp{min@var{m}3}, @samp{max@var{m}3} ++@item @samp{min@var{m}3}, @samp{max@var{m}3} + Floating point min and max operations. If both operands are zeros, + or if either operand is NaN, then it is unspecified which of the two + operands is returned as the result. +--- gcc/doc/rtl.texi.jj 2005-11-21 14:35:16.000000000 +0100 ++++ gcc/doc/rtl.texi 2013-02-20 17:03:16.186985076 +0100 +@@ -2747,11 +2747,9 @@ represents @var{x} before @var{x} is mod + @var{m} must be the machine mode for pointers on the machine in use. + + The expression @var{y} must be one of three forms: +-@table @code + @code{(plus:@var{m} @var{x} @var{z})}, + @code{(minus:@var{m} @var{x} @var{z})}, or + @code{(plus:@var{m} @var{x} @var{i})}, +-@end table + where @var{z} is an index register and @var{i} is a constant. + + Here is an example of its use: +--- gcc/doc/extend.texi.jj 2005-11-21 14:35:16.000000000 +0100 ++++ gcc/doc/extend.texi 2013-02-20 17:00:22.298909603 +0100 +@@ -3707,12 +3707,15 @@ If you replaced @code{short_a} with @cod + declaration, the above program would abort when compiled with + @option{-fstrict-aliasing}, which is on by default at @option{-O2} or + above in recent GCC versions. ++@end table + + @subsection i386 Type Attributes + + Two attributes are currently defined for i386 configurations: + @code{ms_struct} and @code{gcc_struct} + ++@table @code ++ + @item ms_struct + @itemx gcc_struct + @cindex @code{ms_struct} +--- gcc/doc/cppopts.texi.jj 2005-11-21 14:35:16.000000000 +0100 ++++ gcc/doc/cppopts.texi 2013-02-20 16:50:47.462174811 +0100 +@@ -671,7 +671,7 @@ Replacement: [ ] @{ @} + Enable special code to work around file systems which only permit very + short file names, such as MS-DOS@. + +-@itemx --help ++@item --help + @itemx --target-help + @opindex help + @opindex target-help +--- gcc/doc/c-tree.texi.jj 2005-11-21 14:35:16.000000000 +0100 ++++ gcc/doc/c-tree.texi 2013-02-20 17:00:55.106732345 +0100 +@@ -2065,7 +2065,7 @@ corresponding operators in C or C++, but + generate these expressions anyhow, if it can tell that strictness does + not matter. + +-@itemx PLUS_EXPR ++@item PLUS_EXPR + @itemx MINUS_EXPR + @itemx MULT_EXPR + @itemx TRUNC_DIV_EXPR diff --git a/SOURCES/gcc34-pr8788.patch b/SOURCES/gcc34-pr8788.patch new file mode 100644 index 0000000..a08b498 --- /dev/null +++ b/SOURCES/gcc34-pr8788.patch @@ -0,0 +1,42 @@ +2005-05-08 Roger Sayle + + PR inline-asm/8788 + * stmt.c (expand_asm_operands): Avoid calling force_reg on BLKmode + operands. + + * gcc.dg/pr8788-1.c: New testcase. + +--- gcc/stmt.c (revision 99421) ++++ gcc/stmt.c (revision 99422) +@@ -1703,7 +1703,7 @@ expand_asm_operands (tree string, tree o + + if (asm_operand_ok (op, constraint) <= 0) + { +- if (allows_reg) ++ if (allows_reg && TYPE_MODE (type) != BLKmode) + op = force_reg (TYPE_MODE (type), op); + else if (!allows_mem) + warning ("asm operand %d probably doesn't match constraints", +--- gcc/testsuite/gcc.dg/pr8788-1.c (revision 0) ++++ gcc/testsuite/gcc.dg/pr8788-1.c (revision 99422) +@@ -0,0 +1,20 @@ ++/* PR inline-asm/8788 */ ++/* { dg-do compile } */ ++/* { dg-options "-O2" } */ ++ ++typedef struct { ++ long x[6]; ++} myjmp_buf; ++ ++typedef struct { ++ myjmp_buf regs; ++} my_stack; ++ ++void switch_to_stack (my_stack *stack){ ++ asm ( /* { dg-error "impossible constraint" } */ ++/* { dg-warning "asm operand 1" "asm operand 1" { target *-*-* } 14 } */ ++ "\n" ++ : "+r" (stack->regs) ++ ); ++} ++ diff --git a/SOURCES/gcc34-rh137200.patch b/SOURCES/gcc34-rh137200.patch new file mode 100644 index 0000000..adfcf63 --- /dev/null +++ b/SOURCES/gcc34-rh137200.patch @@ -0,0 +1,333 @@ +2005-11-30 Alexandre Oliva + + * gcc.c (find_a_file): Use update_path before access tests. + Mostly from Thomas Walker + * prefix.c (update_path): Move dir/../-stripping code to... + (maybe_strip_dotdots): New function. Reorganize. + +--- gcc/gcc.c.orig 2005-12-01 18:38:38.000000000 -0200 ++++ gcc/gcc.c 2005-12-01 18:41:01.000000000 -0200 +@@ -2371,7 +2371,7 @@ + find_a_file (struct path_prefix *pprefix, const char *name, int mode, + int multilib) + { +- char *temp; ++ char *temp, *temp2; + const char *const file_suffix = + ((mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : ""); + struct prefix_list *pl; +@@ -2407,19 +2407,18 @@ + NULL)); + } + +- temp = xmalloc (len); +- + /* Determine the filename to execute (special case for absolute paths). */ + + if (IS_ABSOLUTE_PATH (name)) + { +- if (access (name, mode) == 0) +- { +- strcpy (temp, name); +- return temp; +- } ++ /* IS_ABSOLUTE_PATHNAME lets anything through that starts with '/' */ ++ temp = update_path (name, NULL); ++ if (access (temp, mode) == 0) ++ return temp; + } + else ++ { ++ temp = xmalloc (len); + for (pl = pprefix->plist; pl; pl = pl->next) + { + const char *this_name +@@ -2435,24 +2434,30 @@ + strcat (temp, machine_suffix); + strcat (temp, multilib_name); + strcat (temp, file_suffix); +- if (access_check (temp, mode) == 0) ++ temp2 = update_path (temp, NULL); ++ if (access_check (temp2, mode) == 0) + { + if (pl->used_flag_ptr != 0) + *pl->used_flag_ptr = 1; +- return temp; ++ free (temp); ++ return temp2; + } ++ free (temp2); + } + + /* Now try just the multilib_name. */ + strcpy (temp, pl->prefix); + strcat (temp, machine_suffix); + strcat (temp, multilib_name); +- if (access_check (temp, mode) == 0) ++ temp2 = update_path (temp, NULL); ++ if (access_check (temp2, mode) == 0) + { + if (pl->used_flag_ptr != 0) + *pl->used_flag_ptr = 1; +- return temp; ++ free (temp); ++ return temp2; + } ++ free (temp2); + } + + /* Certain prefixes are tried with just the machine type, +@@ -2467,23 +2472,29 @@ + strcat (temp, just_machine_suffix); + strcat (temp, multilib_name); + strcat (temp, file_suffix); +- if (access_check (temp, mode) == 0) ++ temp2 = update_path (temp, NULL); ++ if (access_check (temp2, mode) == 0) + { + if (pl->used_flag_ptr != 0) + *pl->used_flag_ptr = 1; +- return temp; ++ free (temp); ++ return temp2; + } ++ free (temp2); + } + + strcpy (temp, pl->prefix); + strcat (temp, just_machine_suffix); + strcat (temp, multilib_name); +- if (access_check (temp, mode) == 0) ++ temp2 = update_path (temp, NULL); ++ if (access_check (temp2, mode) == 0) + { + if (pl->used_flag_ptr != 0) + *pl->used_flag_ptr = 1; +- return temp; ++ free (temp); ++ return temp2; + } ++ free (temp2); + } + + /* Certain prefixes can't be used without the machine suffix +@@ -2497,24 +2508,31 @@ + strcpy (temp, pl->prefix); + strcat (temp, this_name); + strcat (temp, file_suffix); +- if (access_check (temp, mode) == 0) ++ temp2 = update_path (temp, NULL); ++ if (access_check (temp2, mode) == 0) + { + if (pl->used_flag_ptr != 0) + *pl->used_flag_ptr = 1; +- return temp; ++ free (temp); ++ return temp2; + } ++ free (temp2); + } + + strcpy (temp, pl->prefix); + strcat (temp, this_name); +- if (access_check (temp, mode) == 0) ++ temp2 = update_path (temp, NULL); ++ if (access_check (temp2, mode) == 0) + { + if (pl->used_flag_ptr != 0) + *pl->used_flag_ptr = 1; +- return temp; ++ free (temp); ++ return temp2; + } ++ free (temp2); + } + } ++ } + + free (temp); + return 0; +--- gcc/prefix.c.orig 2005-12-01 18:38:38.000000000 -0200 ++++ gcc/prefix.c 2005-12-01 18:46:37.000000000 -0200 +@@ -238,6 +238,105 @@ + while (*string++); + } + ++/* Strip dir/.. from a pathname when it makes sense, e.g., when this ++ would turn an inaccessible pathname into an accessible one. ++ ++ We short-circuit dir/.. when dir does not exist, and when ++ some/dir/../thing does not exist but some/thing does. In case ++ there are multiple possible dir/../ stripping possibilities that ++ would turn an inaccessible pathname into an accessible one, the one ++ closer to the end of the pathname is preferred. ++ ++ RESULT is the pathname that might contain such dotdot sequences to ++ be stripped. P points into RESULT, and indicates the location ++ where we should start looking for ../ sequences. ++ ++ Even though RESULT is const, P is not, and that's because ++ characters in it may be temporarily overwritten, so RESULT must not ++ be in read-only storage. ++ ++ The returned value is either a newly-allocated memory area, holding ++ a string that is the result of dotdot-stripping from the original ++ input strip, or RESULT itself, in which case any modifications made ++ to the string will have been undone. */ ++ ++static const char * ++maybe_strip_dotdots (const char *result, char *p) ++{ ++ char *temp; ++ const char *path, *before, *after; ++ size_t len; ++ ++ while (1) ++ { ++ p = strchr (p, '.'); ++ if (p == NULL) ++ return result; ++ /* Look for `/../' */ ++ if (p[1] == '.' ++ && IS_DIR_SEPARATOR (p[2]) ++ && (p != result && IS_DIR_SEPARATOR (p[-1]))) ++ break; ++ else ++ ++p; ++ } ++ ++ *p = 0; ++ if (access (result, X_OK) == 0) ++ { ++ *p = '.'; ++ ++ path = maybe_strip_dotdots (result, p + 3); ++ if (access (path, F_OK) == 0) ++ return path; ++ if (path != result) ++ free ((char *) path); ++ } ++ else ++ *p = '.'; ++ ++ /* If we couldn't access the dir, or if recursion resulted in a ++ non-accessible pathname, we try stripping out dir/../. If `dir' ++ turns out to be `.', strip one more path component. */ ++ before = p; ++ do ++ { ++ --before; ++ while (before != result && IS_DIR_SEPARATOR (*before)) ++ --before; ++ while (before != result && !IS_DIR_SEPARATOR (before[-1])) ++ --before; ++ } ++ while (before != result && *before == '.' ++ && IS_DIR_SEPARATOR (*(before + 1))); ++ /* If we have something like `./..' or `/..', don't ++ strip anything more. */ ++ if (*before == '.' || IS_DIR_SEPARATOR (*before)) ++ return result; ++ ++ after = p + 3; ++ while (IS_DIR_SEPARATOR (*after)) ++ ++after; ++ ++ len = (after - result) + strlen (after); ++ ++ temp = xmalloc (len + 1 - (after - before)); ++ memcpy (temp, result, before - result); ++ memcpy (temp + (before - result), after, len + 1 - (after - result)); ++ ++ path = maybe_strip_dotdots (temp, temp + (before - result)); ++ ++ if (path != temp) ++ free (temp); ++ ++ if (access (path, F_OK) == 0) ++ result = path; ++ else if (path != result) ++ free ((char *) path); ++ ++ return result; ++} ++ + /* Update PATH using KEY if PATH starts with PREFIX. The returned + string is always malloc-ed, and the caller is responsible for + freeing it. */ +@@ -245,7 +344,7 @@ + char * + update_path (const char *path, const char *key) + { +- char *result, *p; ++ char *result, *temp; + + if (! strncmp (path, std_prefix, strlen (std_prefix)) && key != 0) + { +@@ -265,62 +364,11 @@ + else + result = xstrdup (path); + +-#ifndef ALWAYS_STRIP_DOTDOT +-#define ALWAYS_STRIP_DOTDOT 0 +-#endif ++ temp = result; ++ result = (char *) maybe_strip_dotdots (temp, temp); + +- p = result; +- while (1) +- { +- char *src, *dest; +- +- p = strchr (p, '.'); +- if (p == NULL) +- break; +- /* Look for `/../' */ +- if (p[1] == '.' +- && IS_DIR_SEPARATOR (p[2]) +- && (p != result && IS_DIR_SEPARATOR (p[-1]))) +- { +- *p = 0; +- if (!ALWAYS_STRIP_DOTDOT && access (result, X_OK) == 0) +- { +- *p = '.'; +- break; +- } +- else +- { +- /* We can't access the dir, so we won't be able to +- access dir/.. either. Strip out `dir/../'. If `dir' +- turns out to be `.', strip one more path component. */ +- dest = p; +- do +- { +- --dest; +- while (dest != result && IS_DIR_SEPARATOR (*dest)) +- --dest; +- while (dest != result && !IS_DIR_SEPARATOR (dest[-1])) +- --dest; +- } +- while (dest != result && *dest == '.'); +- /* If we have something like `./..' or `/..', don't +- strip anything more. */ +- if (*dest == '.' || IS_DIR_SEPARATOR (*dest)) +- { +- *p = '.'; +- break; +- } +- src = p + 3; +- while (IS_DIR_SEPARATOR (*src)) +- ++src; +- p = dest; +- while ((*dest++ = *src++) != 0) +- ; +- } +- } +- else +- ++p; +- } ++ if (result != temp) ++ free (temp); + + #ifdef UPDATE_PATH_HOST_CANONICALIZE + /* Perform host dependent canonicalization when needed. */ diff --git a/SOURCES/gcc34-rh156291.patch b/SOURCES/gcc34-rh156291.patch new file mode 100644 index 0000000..34858ce --- /dev/null +++ b/SOURCES/gcc34-rh156291.patch @@ -0,0 +1,29 @@ +2005-09-29 Alexandre Oliva + + * error.c (dump_type) : Print reworded message. + + * g++.dg/overload/unknown1.C: New. + +--- gcc/cp/error.c.orig 2004-11-07 11:22:11.000000000 -0200 ++++ gcc/cp/error.c 2005-09-29 16:13:20.000000000 -0300 +@@ -302,7 +302,7 @@ + switch (TREE_CODE (t)) + { + case UNKNOWN_TYPE: +- pp_identifier (cxx_pp, ""); ++ pp_identifier (cxx_pp, ""); + break; + + case TREE_LIST: +--- gcc/testsuite/g++.dg/overload/unknown1.C 1970-01-01 00:00:00.000000000 +0000 ++++ gcc/testsuite/g++.dg/overload/unknown1.C 2005-09-29 16:12:49.000000000 -0300 +@@ -0,0 +1,9 @@ ++// { dg-do compile } ++ ++void foo(void); ++int foo(int); ++template void bar(T f); ++ ++void baz() { ++ bar(foo); // { dg-error "" } ++} diff --git a/SOURCES/gcc34-rh172117.patch b/SOURCES/gcc34-rh172117.patch new file mode 100644 index 0000000..bb3dd31 --- /dev/null +++ b/SOURCES/gcc34-rh172117.patch @@ -0,0 +1,109 @@ +2005-12-18 Alexandre Oliva + + * optabs.c (expand_vector_binop): Do not use a SUBREG to modify + a subword in the output if it matches any of the inputs. + +2006-04-20 Jakub Jelinek + + * gcc.c-torture/execute/20060420-1.c: New test. + +--- gcc/optabs.c.orig 2005-11-21 11:43:20.000000000 -0200 ++++ gcc/optabs.c 2005-12-18 18:35:14.000000000 -0200 +@@ -1933,16 +1933,19 @@ + + for (i = 0; i < elts; ++i) + { +- /* If this is part of a register, and not the first item in the +- word, we can't store using a SUBREG - that would clobber +- previous results. ++ /* If this is part of a register, and not the first item in ++ the word, we can't store using a SUBREG - that would ++ clobber previous results, or even the input operands, if ++ target matches any of them. + And storing with a SUBREG is only possible for the least + significant part, hence we can't do it for big endian + (unless we want to permute the evaluation order. */ + if (GET_CODE (target) == REG + && (BYTES_BIG_ENDIAN + ? subsize < UNITS_PER_WORD +- : ((i * subsize) % UNITS_PER_WORD) != 0)) ++ : (((i * subsize) % UNITS_PER_WORD) != 0 ++ || (subsize < UNITS_PER_WORD ++ && (target == op0 || target == op1))))) + t = NULL_RTX; + else + t = simplify_gen_subreg (submode, target, mode, i * subsize); +--- gcc/testsuite/gcc.c-torture/execute/20060420-1.c.jj 2006-04-20 18:47:19.000000000 +0200 ++++ gcc/testsuite/gcc.c-torture/execute/20060420-1.c 2006-04-20 19:07:20.000000000 +0200 +@@ -0,0 +1,71 @@ ++extern void abort (void); ++ ++typedef float v4flt __attribute__ ((vector_size (16))); ++ ++void __attribute__ ((noinline)) foo (float *dst, float **src, int a, int n) ++{ ++ int i, j; ++ int z = sizeof (v4flt) / sizeof (float); ++ unsigned m = sizeof (v4flt) - 1; ++ ++ for (j = 0; j < n && (((unsigned long) dst + j) & m); ++j) ++ { ++ float t = src[0][j]; ++ for (i = 1; i < a; ++i) ++ t += src[i][j]; ++ dst[j] = t; ++ } ++ ++ for (; j < (n - (4 * z - 1)); j += 4 * z) ++ { ++ v4flt t0 = *(v4flt *) (src[0] + j + 0 * z); ++ v4flt t1 = *(v4flt *) (src[0] + j + 1 * z); ++ v4flt t2 = *(v4flt *) (src[0] + j + 2 * z); ++ v4flt t3 = *(v4flt *) (src[0] + j + 3 * z); ++ for (i = 1; i < a; ++i) ++ { ++ t0 += *(v4flt *) (src[i] + j + 0 * z); ++ t1 += *(v4flt *) (src[i] + j + 1 * z); ++ t2 += *(v4flt *) (src[i] + j + 2 * z); ++ t3 += *(v4flt *) (src[i] + j + 3 * z); ++ } ++ *(v4flt *) (dst + j + 0 * z) = t0; ++ *(v4flt *) (dst + j + 1 * z) = t1; ++ *(v4flt *) (dst + j + 2 * z) = t2; ++ *(v4flt *) (dst + j + 3 * z) = t3; ++ } ++ for (; j < n; ++j) ++ { ++ float t = src[0][j]; ++ for (i = 1; i < a; ++i) ++ t += src[i][j]; ++ dst[j] = t; ++ } ++} ++ ++float buffer[64]; ++ ++int ++main (void) ++{ ++ int i; ++ float *dst, *src[2]; ++ ++ dst = buffer; ++ dst += (-(long int) buffer & (16 * sizeof (float) - 1)) / sizeof (float); ++ src[0] = dst + 16; ++ src[1] = dst + 32; ++ for (i = 0; i < 16; ++i) ++ { ++ src[0][i] = (float) i + 11 * (float) i; ++ src[1][i] = (float) i + 12 * (float) i; ++ } ++ foo (dst, src, 2, 16); ++ for (i = 0; i < 16; ++i) ++ { ++ float e = (float) i + 11 * (float) i + (float) i + 12 * (float) i; ++ if (dst[i] != e) ++ abort (); ++ } ++ return 0; ++} diff --git a/SOURCES/gcc34-rh172876.patch b/SOURCES/gcc34-rh172876.patch new file mode 100644 index 0000000..4da6ff2 --- /dev/null +++ b/SOURCES/gcc34-rh172876.patch @@ -0,0 +1,73 @@ +2006-03-01 Alexandre Oliva + + * dwarf2out.c (dwarf2out_stack_adjust): Always track the stack + pointer, instead of assuming it is possible to derive the + correct args size from a call insn. + +--- gcc/dwarf2out.c.orig 2006-03-01 05:13:50.000000000 -0300 ++++ gcc/dwarf2out.c 2006-03-01 05:41:38.000000000 -0300 +@@ -1069,26 +1069,6 @@ dwarf2out_stack_adjust (rtx insn) + if (prologue_epilogue_contains (insn) || sibcall_epilogue_contains (insn)) + return; + +- if (!flag_asynchronous_unwind_tables && GET_CODE (insn) == CALL_INSN) +- { +- /* Extract the size of the args from the CALL rtx itself. */ +- insn = PATTERN (insn); +- if (GET_CODE (insn) == PARALLEL) +- insn = XVECEXP (insn, 0, 0); +- if (GET_CODE (insn) == SET) +- insn = SET_SRC (insn); +- if (GET_CODE (insn) != CALL) +- abort (); +- +- dwarf2out_args_size ("", INTVAL (XEXP (insn, 1))); +- return; +- } +- +- /* If only calls can throw, and we have a frame pointer, +- save up adjustments until we see the CALL_INSN. */ +- else if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM) +- return; +- + if (GET_CODE (insn) == BARRIER) + { + /* When we see a BARRIER, we know to reset args_size to 0. Usually +@@ -1111,9 +1091,20 @@ dwarf2out_stack_adjust (rtx insn) + if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET) + offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i)); + } ++ else if (GET_CODE (insn) == CALL_INSN) ++ offset = 0; + else + return; + ++ /* We handle this separately because we want stack adjustments in a ++ CALL_INSN to be handled. */; ++ if (GET_CODE (insn) == CALL_INSN) ++ { ++ /* If only calls can throw, adjust args_size only at call sites. */ ++ if (!flag_asynchronous_unwind_tables) ++ dwarf2out_args_size ("", args_size); ++ } ++ + if (offset == 0) + return; + +@@ -1128,6 +1119,16 @@ dwarf2out_stack_adjust (rtx insn) + if (args_size < 0) + args_size = 0; + ++ /* If only calls can throw and we have a frame pointer, we'll save ++ up adjustments until we see the CALL_INSN. We used to return ++ early and derive args_size from NARGS in the CALL_INSN itself, ++ but that doesn't compute the right value if we have nested call ++ expansions, e.g., stack adjustments for a call have already been ++ emitted, and then we issue another call to compute an argument ++ for the enclosing call (i.e., bar (foo ())). */ ++ if (!flag_asynchronous_unwind_tables && cfa.reg != STACK_POINTER_REGNUM) ++ return; ++ + label = dwarf2out_cfi_label (); + def_cfa_1 (label, &cfa); + dwarf2out_args_size (label, args_size); diff --git a/SOURCES/gcc34-rh176182.patch b/SOURCES/gcc34-rh176182.patch new file mode 100644 index 0000000..6652303 --- /dev/null +++ b/SOURCES/gcc34-rh176182.patch @@ -0,0 +1,53 @@ +2005-10-31 James E. Wilson + + PR debug/24444 + * dwarf2out.c (convert_cfa_to_loc_list): Put inside DWARF2_UNWIND_INFO + ifdef. Put ifdefs around call in gen_subprogram_die. + (compute_frame_pointer_to_cfa_displacement): Likewise. + (gen_subprogram_die): Restore old code for when DWARF2_UNWIND_INFO is + not defined. + +--- gcc/dwarf2out.c.orig 2005-11-21 07:57:57.000000000 -0200 ++++ gcc/dwarf2out.c 2005-12-20 16:46:22.000000000 -0200 +@@ -10047,6 +10047,7 @@ tree_add_const_value_attribute (dw_die_r + } + } + ++#ifdef DWARF2_UNWIND_INFO + /* Convert the CFI instructions for the current function into a location + list. This is used for DW_AT_frame_base when we targeting a dwarf2 + consumer that does not support the dwarf3 DW_OP_call_frame_cfa. */ +@@ -10138,6 +10139,7 @@ compute_frame_pointer_to_cfa_displacemen + + frame_pointer_cfa_offset = -offset; + } ++#endif + + /* Generate a DW_AT_name attribute given some string value to be included as + the value of the attribute. */ +@@ -11385,6 +11387,7 @@ gen_subprogram_die (tree decl, dw_die_re + add_AT_fde_ref (subr_die, DW_AT_MIPS_fde, current_funcdef_fde); + #endif + ++#ifdef DWARF2_UNWIND_INFO + /* We define the "frame base" as the function's CFA. This is more + convenient for several reasons: (1) It's stable across the prologue + and epilogue, which makes it better than just a frame pointer, +@@ -11411,6 +11414,17 @@ gen_subprogram_die (tree decl, dw_die_re + debugger about. We'll need to adjust all frame_base references + by this displacement. */ + compute_frame_pointer_to_cfa_displacement (); ++#else ++ /* For targets which support DWARF2, but not DWARF2 call-frame info, ++ we just use the stack pointer or frame pointer. */ ++ /* ??? Should investigate getting better info via callbacks, or else ++ by interpreting the IA-64 unwind info. */ ++ { ++ rtx fp_reg ++ = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; ++ add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); ++ } ++#endif + + #if 0 + /* ??? This fails for nested inline functions, because context_display diff --git a/SOURCES/gcc34-rh178062.patch b/SOURCES/gcc34-rh178062.patch new file mode 100644 index 0000000..5e6a384 --- /dev/null +++ b/SOURCES/gcc34-rh178062.patch @@ -0,0 +1,56 @@ +2006-02-25 Alexandre Oliva + + * varasm.c (copy_constant): Handle VECTOR_CST. + + * gcc.dg/altivec-23.c: New test. + +--- gcc/varasm.c 2006-02-25 03:52:54.000000000 -0300 ++++ gcc/varasm.c 2006-02-25 03:54:56.000000000 -0300 +@@ -2464,6 +2464,19 @@ copy_constant (tree exp) + return copy; + } + ++ case VECTOR_CST: ++ { ++ tree copy = copy_node (exp); ++ tree list = copy_list (TREE_VECTOR_CST_ELTS (exp)); ++ tree tail; ++ ++ TREE_VECTOR_CST_ELTS (copy) = list; ++ for (tail = list; tail; tail = TREE_CHAIN (tail)) ++ TREE_VALUE (tail) = copy_constant (TREE_VALUE (tail)); ++ ++ return copy; ++ } ++ + default: + { + tree t; +--- gcc/testsuite/gcc.dg/altivec-23.c 1970-01-01 00:00:00.000000000 +0000 ++++ gcc/testsuite/gcc.dg/altivec-23.c 2006-02-25 04:10:36.000000000 -0300 +@@ -0,0 +1,25 @@ ++/* Verify that it is possible to define variables of composite types ++ containing vector types. We used to crash handling the ++ initializer of automatic ones. */ ++ ++/* { dg-do compile { target powerpc*-*-* } } */ ++/* { dg-xfail-if "" { "powerpc-ibm-aix*" } { "-maltivec" } { "" } } */ ++/* { dg-options "-maltivec -mabi=altivec" } */ ++ ++#include ++ ++typedef int bt; ++typedef vector bt vt; ++typedef struct { vt x; bt y[sizeof(vt) / sizeof (bt)]; } st; ++#define INIT { 1, 2, 3, 4 } ++ ++void f () ++{ ++ vt x = INIT; ++ vt y[1] = { INIT }; ++ st s = { INIT, INIT }; ++} ++ ++vt x = INIT; ++vt y[1] = { INIT }; ++st s = { INIT, INIT }; diff --git a/SOURCES/gcc34-rh205919.patch b/SOURCES/gcc34-rh205919.patch new file mode 100644 index 0000000..9808285 --- /dev/null +++ b/SOURCES/gcc34-rh205919.patch @@ -0,0 +1,45 @@ +2006-12-08 Alexandre Oliva + + * g++.dg/template/array17.C: New test. + +2006-10-27 Alexandre Oliva + + * typeck.c (non_reference): Don't dereference NULL type. + +--- gcc/cp/typeck.c.orig 2005-11-21 11:56:03.000000000 -0200 ++++ gcc/cp/typeck.c 2006-10-27 03:28:04.000000000 -0300 +@@ -6443,7 +6443,7 @@ casts_away_constness (tree t1, tree t2) + tree + non_reference (tree t) + { +- if (TREE_CODE (t) == REFERENCE_TYPE) ++ if (t != NULL_TREE && TREE_CODE (t) == REFERENCE_TYPE) + t = TREE_TYPE (t); + return t; + } +--- gcc/testsuite/g++.dg/template/array17.C 2006-10-04 16:28:56.502613000 +0200 ++++ gcc/testsuite/g++.dg/template/array17.C 2006-12-08 12:38:27.000000000 +0100 +@@ -0,0 +1,23 @@ ++// { dg-do compile } ++ ++template ++struct V { ++ T& operator[](int); ++}; ++ ++struct S { ++ S operator +(int); ++ template T value(); ++}; ++ ++template ++void R (T v) ++{ ++ v[(S() + 0).template value()][0] = 0; ++} ++ ++int ++main () ++{ ++ R(V >()); ++} diff --git a/SOURCES/gcc34-rh207277.patch b/SOURCES/gcc34-rh207277.patch new file mode 100644 index 0000000..24ae85d --- /dev/null +++ b/SOURCES/gcc34-rh207277.patch @@ -0,0 +1,111 @@ +2006-12-08 Jakub Jelinek + + * g++.dg/opt/ifcvt1.C: New test. + +2005-11-09 Eric Botcazou + + * ifcvt.c (noce_get_alt_condition): Use prev_nonnote_insn. + (noce_try_abs): Negate if the comparison is reversed. + Look only one instruction backwards for a REG_EQUAL note. + + * gcc.dg/ifcvt-fabs-1.c: New test. + +--- gcc/ifcvt.c.orig 2005-11-21 11:43:21.000000000 -0200 ++++ gcc/ifcvt.c 2006-10-26 02:21:07.000000000 -0300 +@@ -1406,7 +1406,7 @@ noce_get_alt_condition (struct noce_if_i + rtx prev_insn; + + /* First, look to see if we put a constant in a register. */ +- prev_insn = PREV_INSN (if_info->cond_earliest); ++ prev_insn = prev_nonnote_insn (if_info->cond_earliest); + if (prev_insn + && INSN_P (prev_insn) + && GET_CODE (PATTERN (prev_insn)) == SET) +@@ -1642,25 +1642,30 @@ noce_try_abs (struct noce_if_info *if_in + if (rtx_equal_p (XEXP (cond, 0), b)) + c = XEXP (cond, 1); + else if (rtx_equal_p (XEXP (cond, 1), b)) +- c = XEXP (cond, 0); ++ { ++ c = XEXP (cond, 0); ++ negate = !negate; ++ } + else + return FALSE; + +- /* Verify that C is zero. Search backward through the block for +- a REG_EQUAL note if necessary. */ ++ /* Verify that C is zero. Search one step backward for a ++ REG_EQUAL note or a simple source if necessary. */ + if (REG_P (c)) + { +- rtx insn, note = NULL; +- for (insn = earliest; +- insn != BB_HEAD (if_info->test_bb); +- insn = PREV_INSN (insn)) +- if (INSN_P (insn) +- && ((note = find_reg_note (insn, REG_EQUAL, c)) +- || (note = find_reg_note (insn, REG_EQUIV, c)))) +- break; +- if (! note) ++ rtx set, insn = prev_nonnote_insn (earliest); ++ if (insn ++ && (set = single_set (insn)) ++ && rtx_equal_p (SET_DEST (set), c)) ++ { ++ rtx note = find_reg_equal_equiv_note (insn); ++ if (note) ++ c = XEXP (note, 0); ++ else ++ c = SET_SRC (set); ++ } ++ else + return FALSE; +- c = XEXP (note, 0); + } + if (GET_CODE (c) == MEM + && GET_CODE (XEXP (c, 0)) == SYMBOL_REF +--- gcc/testsuite/gcc.dg/ifcvt-fabs-1.c 1970-01-01 00:00:00.000000000 +0000 ++++ gcc/testsuite/gcc.dg/ifcvt-fabs-1.c 2006-10-26 02:20:24.000000000 -0300 +@@ -0,0 +1,21 @@ ++/* { dg-do run } */ ++/* { dg-options "-O" } */ ++/* { dg-options "-O -march=i686" { target i686-*-* } } */ ++ ++extern void abort(void); ++ ++float foo(float f) ++{ ++ if (f < 0.0f) ++ f = -f; ++ ++ return f; ++} ++ ++int main(void) ++{ ++ if (foo (-1.0f) != 1.0f) ++ abort (); ++ ++ return 0; ++} +--- gcc/testsuite/g++.dg/opt/ifcvt1.C 2006-10-04 16:28:56.502613000 +0200 ++++ gcc/testsuite/g++.dg/opt/ifcvt1.C 2006-12-08 12:23:23.000000000 +0100 +@@ -0,0 +1,17 @@ ++// { dg-do compile } ++// { dg-options "-O2 -fnon-call-exceptions" } ++ ++struct S { ~S () throw () {} }; ++double bar (); ++ ++int ++foo () ++{ ++ S a; ++ int i = 0; ++ double c = bar (); ++ c = c < 0 ? -c : c; ++ if (c <= 1.e-8) ++ i += 24; ++ return i; ++} diff --git a/SOURCES/gcc34-rh233941.patch b/SOURCES/gcc34-rh233941.patch new file mode 100644 index 0000000..6c61015 --- /dev/null +++ b/SOURCES/gcc34-rh233941.patch @@ -0,0 +1,43 @@ +2007-04-02 Jakub Jelinek + + * expr.c (expand_expr_real) : Force op1 + into register if target overlaps with op1. + + * g77.f-torture/execute/20070402.f: New test. + +--- gcc/expr.c.jj 2006-10-05 00:37:01.000000000 +0200 ++++ gcc/expr.c 2007-04-02 13:28:52.000000000 +0200 +@@ -8949,6 +8949,9 @@ expand_expr_real (tree exp, rtx target, + + if (! target) + target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp))); ++ else if (GET_CODE (target) == MEM ++ && reg_overlap_mentioned_p (target, op1)) ++ op1 = force_reg (mode, op1); + + start_sequence (); + +--- gcc/testsuite/g77.f-torture/execute/20070402.f.jj 2007-04-02 13:29:51.000000000 +0200 ++++ gcc/testsuite/g77.f-torture/execute/20070402.f 2007-04-02 12:11:00.000000000 +0200 +@@ -0,0 +1,21 @@ ++ program rh233941 ++ implicit none ++ complex*16 z ++ z = dcmplx(1.0, 2.0) ++ call sub(z) ++ stop ++ end program rh233941 ++ ++ subroutine sub(z) ++ implicit none ++ complex*16 z ++ z = dcmplx(-dimag(z), dreal(z)) ++ call sub2(z) ++ return ++ end subroutine sub ++ ++ subroutine sub2(z) ++ implicit none ++ complex*16 z ++ if (dreal(z).ne.-2.0.or.dimag(z).ne.1.0) call abort ++ end subroutine sub2 diff --git a/SOURCES/gcc34-rh234515.patch b/SOURCES/gcc34-rh234515.patch new file mode 100644 index 0000000..ffe4b32 --- /dev/null +++ b/SOURCES/gcc34-rh234515.patch @@ -0,0 +1,73 @@ +2007-01-24 Steve LoBasso + Paolo Carlini + + * include/bits/deque.tcc (deque<>::erase(iterator, iterator)): + Fix condition. + * testsuite/23_containers/deque/modifiers/erase/3.cc: New. + +--- libstdc++-v3/include/bits/deque.tcc (revision 121146) ++++ libstdc++-v3/include/bits/deque.tcc (revision 121147) +@@ -140,7 +140,7 @@ namespace _GLIBCXX_STD + { + const difference_type __n = __last - __first; + const difference_type __elems_before = __first - this->_M_impl._M_start; +- if (static_cast(__elems_before) < (size() - __n) / 2) ++ if (static_cast(__elems_before) <= (size() - __n) / 2) + { + std::copy_backward(this->_M_impl._M_start, __first, __last); + iterator __new_start = this->_M_impl._M_start + __n; +--- libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/3.cc (revision 0) ++++ libstdc++-v3/testsuite/23_containers/deque/modifiers/erase/3.cc (revision 121147) +@@ -0,0 +1,52 @@ ++// Copyright (C) 2007 Free Software Foundation, Inc. ++// ++// This file is part of the GNU ISO C++ Library. This library is free ++// software; you can redistribute it and/or modify it under the ++// terms of the GNU General Public License as published by the ++// Free Software Foundation; either version 2, or (at your option) ++// any later version. ++ ++// This library is distributed in the hope that it will be useful, ++// but WITHOUT ANY WARRANTY; without even the implied warranty of ++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++// GNU General Public License for more details. ++ ++// You should have received a copy of the GNU General Public License along ++// with this library; see the file COPYING. If not, write to the Free ++// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, ++// USA. ++ ++// 23.2.1.3 deque modifiers ++ ++#include ++#include ++ ++void erase(size_t num_elm, size_t elm_strt, size_t elm_end) ++{ ++ bool test __attribute__((unused)) = true; ++ using __gnu_test::copy_tracker; ++ using __gnu_test::assignment_operator; ++ ++ std::deque x(num_elm); ++ copy_tracker::reset(); ++ ++ x.erase(x.begin() + elm_strt, x.begin() + elm_end); ++ ++ const size_t min_num_cpy = std::min(elm_strt, num_elm - elm_end); ++ VERIFY( assignment_operator::count() == min_num_cpy ); ++} ++ ++// http://gcc.gnu.org/ml/libstdc++/2007-01/msg00098.html ++void test01() ++{ ++ for (size_t num_elm = 0; num_elm <= 10; ++num_elm) ++ for (size_t elm_strt = 0; elm_strt <= num_elm; ++elm_strt) ++ for (size_t elm_end = elm_strt; elm_end <= num_elm; ++elm_end) ++ erase(num_elm, elm_strt, elm_end); ++} ++ ++int main() ++{ ++ test01(); ++ return 0; ++} diff --git a/SOURCES/gcc34-rh235008.patch b/SOURCES/gcc34-rh235008.patch new file mode 100644 index 0000000..93c392a --- /dev/null +++ b/SOURCES/gcc34-rh235008.patch @@ -0,0 +1,41 @@ +2007-04-12 Jakub Jelinek + + * fr.po: Use %s rather than %S. + * rw.po: Comment out translations with bogus format + strings. + +--- gcc/po/fr.po.jj 2006-10-05 00:33:36.000000000 +0200 ++++ gcc/po/fr.po 2007-04-13 00:23:29.000000000 +0200 +@@ -17100,7 +17100,7 @@ msgstr "%s liste d'expressions trait�e c + + #: cp/typeck.c:4490 + msgid "%s from type `%T' to type `%T' casts away constness" +-msgstr "%S � partir du � %T � vers le type � %T � provoque un transtypage sans constante" ++msgstr "%s � partir du � %T � vers le type � %T � provoque un transtypage sans constante" + + #: cp/typeck.c:4692 + msgid "invalid static_cast from type `%T' to type `%T'" +--- gcc/po/rw.po.jj 2006-10-05 00:33:36.000000000 +0200 ++++ gcc/po/rw.po 2007-04-13 00:22:28.000000000 +0200 +@@ -2541,8 +2541,8 @@ msgstr "-Imiterere Ikiranga" + + #: c-opts.c:1139 + #, fuzzy, c-format +-msgid "opening output file %s: %m" +-msgstr "Gufungura %s%S Ibisohoka IDOSIYE" ++#~ msgid "opening output file %s: %m" ++#~ msgstr "Gufungura %s%S Ibisohoka IDOSIYE" + + #: c-opts.c:1144 + #, fuzzy, c-format +@@ -2556,8 +2556,8 @@ msgstr "OYA" + + #: c-opts.c:1269 + #, fuzzy, c-format +-msgid "opening dependency file %s: %m" +-msgstr "Gufungura %s%S IDOSIYE" ++#~ msgid "opening dependency file %s: %m" ++#~ msgstr "Gufungura %s%S IDOSIYE" + + #: c-opts.c:1279 + #, fuzzy, c-format diff --git a/SOURCES/gcc34-rh235255.patch b/SOURCES/gcc34-rh235255.patch new file mode 100644 index 0000000..4914ee5 --- /dev/null +++ b/SOURCES/gcc34-rh235255.patch @@ -0,0 +1,142 @@ +2007-04-21 Alexandre Oliva + + * gcse.c (store_killed_in_insn): Handle PARALLELs. + (store_killed_in_pat): New. + + * gcc.dg/movsi-sm-1.c: New. + +--- gcc/gcse.c.jj 2007-02-23 21:29:12.000000000 +0100 ++++ gcc/gcse.c 2007-07-18 20:41:08.000000000 +0200 +@@ -7427,6 +7427,40 @@ find_loads (rtx x, rtx store_pattern, in + return ret; + } + ++static inline bool ++store_killed_in_pat (rtx x, rtx pat, int after) ++{ ++ if (GET_CODE (pat) == SET) ++ { ++ rtx dest = SET_DEST (pat); ++ ++ if (GET_CODE (dest) == SIGN_EXTRACT ++ || GET_CODE (dest) == ZERO_EXTRACT) ++ dest = XEXP (dest, 0); ++ ++ /* Check for memory stores to aliased objects. */ ++ if (GET_CODE (dest) == MEM ++ && !expr_equiv_p (dest, x)) ++ { ++ if (after) ++ { ++ if (output_dependence (dest, x)) ++ return true; ++ } ++ else ++ { ++ if (output_dependence (x, dest)) ++ return true; ++ } ++ } ++ } ++ ++ if (find_loads (pat, x, after)) ++ return true; ++ ++ return false; ++} ++ + /* Check if INSN kills the store pattern X (is aliased with it). + AFTER is true if we are checking the case when store X occurs + after the insn. Return true if it it does. */ +@@ -7434,7 +7468,7 @@ find_loads (rtx x, rtx store_pattern, in + static bool + store_killed_in_insn (rtx x, rtx x_regs, rtx insn, int after) + { +- rtx reg, base, note; ++ rtx reg, base, note, pat; + + if (!INSN_P (insn)) + return false; +@@ -7461,33 +7495,20 @@ store_killed_in_insn (rtx x, rtx x_regs, + return false; + } + +- if (GET_CODE (PATTERN (insn)) == SET) ++ pat = PATTERN (insn); ++ if (GET_CODE (pat) == SET) + { +- rtx pat = PATTERN (insn); +- rtx dest = SET_DEST (pat); +- +- if (GET_CODE (dest) == SIGN_EXTRACT +- || GET_CODE (dest) == ZERO_EXTRACT) +- dest = XEXP (dest, 0); +- +- /* Check for memory stores to aliased objects. */ +- if (GET_CODE (dest) == MEM +- && !expr_equiv_p (dest, x)) +- { +- if (after) +- { +- if (output_dependence (dest, x)) +- return true; +- } +- else +- { +- if (output_dependence (x, dest)) +- return true; +- } +- } +- if (find_loads (SET_SRC (pat), x, after)) ++ if (store_killed_in_pat (x, pat, after)) + return true; + } ++ else if (GET_CODE (pat) == PARALLEL) ++ { ++ int i; ++ ++ for (i = 0; i < XVECLEN (pat, 0); i++) ++ if (store_killed_in_pat (x, XVECEXP (pat, 0, i), after)) ++ return true; ++ } + else if (find_loads (PATTERN (insn), x, after)) + return true; + +--- gcc/testsuite/gcc.dg/movsi-sm-1.c.jj 2007-07-18 20:58:08.000000000 +0200 ++++ gcc/testsuite/gcc.dg/movsi-sm-1.c 2007-07-18 21:01:52.000000000 +0200 +@@ -0,0 +1,35 @@ ++/* { dg-do run } */ ++/* { dg-options "-O2" } */ ++/* { dg-options "-O2 -mtune=i386" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */ ++ ++int ret = 1; ++char buf[128]; ++ ++void ++__attribute__((noinline)) ++bug (int arg) ++{ ++ char str[28]; ++ ++ __builtin_memcpy (str, "Bugged!", 8); ++ ++ if (arg & 0200) ++ { ++ __builtin_memcpy (str, "This is what we should get!", 28); ++ ret = 0; ++ } ++ ++ if (arg & 0100) ++ __builtin_memcpy (str, "Broken!", 8); ++ ++ __builtin_sprintf (buf, "%s\n", str); ++} ++ ++int ++main () ++{ ++ bug (0200); ++ if (ret) ++ return ret; ++ return __builtin_strcmp (buf, "This is what we should get!\n") != 0; ++} diff --git a/SOURCES/gcc34-rh242685.patch b/SOURCES/gcc34-rh242685.patch new file mode 100644 index 0000000..03ace0f --- /dev/null +++ b/SOURCES/gcc34-rh242685.patch @@ -0,0 +1,46 @@ +2007-06-08 Jatin Nansi + + * config/locale/ieee_1003.1-2001/codecvt_specializations.h: Make sure + _M_int_enc and _M_ext_enc are '\0' terminated. + +--- libstdc++-v3/config/locale/ieee_1003.1-2001/codecvt_specializations.h.jj 2007-02-23 21:29:34.000000000 +0100 ++++ libstdc++-v3/config/locale/ieee_1003.1-2001/codecvt_specializations.h 2007-07-19 14:20:20.000000000 +0200 +@@ -83,8 +83,10 @@ + int __ibom = 0, int __ebom = 0) + : _M_in_desc(0), _M_out_desc(0), _M_ext_bom(__ebom), _M_int_bom(__ibom) + { +- strncpy(_M_int_enc, __int, _S_max_size); +- strncpy(_M_ext_enc, __ext, _S_max_size); ++ strncpy(_M_int_enc, __int, _S_max_size - 1); ++ strncpy(_M_ext_enc, __ext, _S_max_size - 1); ++ _M_int_enc[_S_max_size - 1] = '\0'; ++ _M_ext_enc[_S_max_size - 1] = '\0'; + _M_init(); + } + +@@ -98,8 +100,10 @@ + // information. + __enc_traits(const __enc_traits& __obj): _M_in_desc(0), _M_out_desc(0) + { +- strncpy(_M_int_enc, __obj._M_int_enc, _S_max_size); +- strncpy(_M_ext_enc, __obj._M_ext_enc, _S_max_size); ++ strncpy(_M_int_enc, __obj._M_int_enc, _S_max_size - 1); ++ strncpy(_M_ext_enc, __obj._M_ext_enc, _S_max_size - 1); ++ _M_int_enc[_S_max_size - 1] = '\0'; ++ _M_ext_enc[_S_max_size - 1] = '\0'; + _M_ext_bom = __obj._M_ext_bom; + _M_int_bom = __obj._M_int_bom; + _M_destroy(); +@@ -110,8 +114,10 @@ + __enc_traits& + operator=(const __enc_traits& __obj) + { +- strncpy(_M_int_enc, __obj._M_int_enc, _S_max_size); +- strncpy(_M_ext_enc, __obj._M_ext_enc, _S_max_size); ++ strncpy(_M_int_enc, __obj._M_int_enc, _S_max_size - 1); ++ strncpy(_M_ext_enc, __obj._M_ext_enc, _S_max_size - 1); ++ _M_int_enc[_S_max_size - 1] = '\0'; ++ _M_ext_enc[_S_max_size - 1] = '\0'; + _M_ext_bom = __obj._M_ext_bom; + _M_int_bom = __obj._M_int_bom; + _M_destroy(); diff --git a/SOURCES/gcc34-sw2438.patch b/SOURCES/gcc34-sw2438.patch new file mode 100644 index 0000000..8a582cf --- /dev/null +++ b/SOURCES/gcc34-sw2438.patch @@ -0,0 +1,232 @@ +2006-05-23 Alexandre Oliva + + * simplify-rtx.c (simplify_subreg): Adjust REG_OFFSET for + big-endian paradoxical subregs. + * var-tracking.c (struct micro_operation_def): Document that, + for modify micro operations, insn is the subsequent instruction. + (var_reg_delete_and_set, var_mem_delete_and_set): Split into... + (var_reg_set, var_mem_set): ... new functions. + (add_stores): Record subsequent insn. + (compute_bb_dataflow): Use new functions for MO_USE. + (emit_notes_in_bb): Use new functions for MO_USE. Emit use + notes after the insn, and modify notes before the insn known + to be the subsequent one. + (vt_initialize): Invert sorting of MO_CLOBBERs and MO_SETs. + +--- gcc/simplify-rtx.c 2005-11-21 11:55:29.000000000 -0200 ++++ gcc/simplify-rtx.c 2006-05-16 01:47:01.000000000 -0300 +@@ -3473,7 +3473,22 @@ simplify_subreg (enum machine_mode outer + if (HARD_REGNO_MODE_OK (final_regno, outermode) + || ! HARD_REGNO_MODE_OK (REGNO (op), innermode)) + { +- rtx x = gen_rtx_REG_offset (op, outermode, final_regno, byte); ++ rtx x; ++ int final_offset = byte; ++ ++ /* Adjust offset for paradoxical subregs. */ ++ if (byte == 0 ++ && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) ++ { ++ int difference = (GET_MODE_SIZE (innermode) ++ - GET_MODE_SIZE (outermode)); ++ if (WORDS_BIG_ENDIAN) ++ final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; ++ if (BYTES_BIG_ENDIAN) ++ final_offset += difference % UNITS_PER_WORD; ++ } ++ ++ x = gen_rtx_REG_offset (op, outermode, final_regno, final_offset); + + /* Propagate original regno. We don't have any way to specify + the offset inside original regno, so do so only for lowpart. +--- gcc/var-tracking.c 2006-05-10 17:17:51.000000000 -0300 ++++ gcc/var-tracking.c 2006-05-16 03:25:32.000000000 -0300 +@@ -138,7 +138,11 @@ typedef struct micro_operation_def + HOST_WIDE_INT adjust; + } u; + +- /* The instruction which the micro operation is in. */ ++ /* The instruction which the micro operation is in, for MO_USE, ++ MO_USE_NO_VAR, MO_CALL and MO_ADJUST, or the subsequent ++ instruction or note in the original flow (before any var-tracking ++ notes are inserted, to simplify emission of notes), for MO_SET ++ and MO_CLOBBER. */ + rtx insn; + } micro_operation; + +@@ -289,9 +293,11 @@ static void vars_clear (htab_t); + static variable unshare_variable (dataflow_set *set, variable var); + static int vars_copy_1 (void **, void *); + static void vars_copy (htab_t, htab_t); ++static void var_reg_set (dataflow_set *, rtx); + static void var_reg_delete_and_set (dataflow_set *, rtx); + static void var_reg_delete (dataflow_set *, rtx); + static void var_regno_delete (dataflow_set *, int); ++static void var_mem_set (dataflow_set *, rtx); + static void var_mem_delete_and_set (dataflow_set *, rtx); + static void var_mem_delete (dataflow_set *, rtx); + +@@ -788,6 +794,19 @@ vars_copy (htab_t dst, htab_t src) + htab_traverse (src, vars_copy_1, dst); + } + ++/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ ++ ++static void ++var_reg_set (dataflow_set *set, rtx loc) ++{ ++ tree decl = REG_EXPR (loc); ++ HOST_WIDE_INT offset = REG_OFFSET (loc); ++ ++ if (set->regs[REGNO (loc)] == NULL) ++ attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc); ++ set_variable_part (set, loc, decl, offset); ++} ++ + /* Delete current content of register LOC in dataflow set SET + and set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ + +@@ -815,9 +834,7 @@ var_reg_delete_and_set (dataflow_set *se + nextp = &node->next; + } + } +- if (set->regs[REGNO (loc)] == NULL) +- attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc); +- set_variable_part (set, loc, decl, offset); ++ var_reg_set (set, loc); + } + + /* Delete current content of register LOC in dataflow set SET. */ +@@ -854,12 +871,12 @@ var_regno_delete (dataflow_set *set, int + *reg = NULL; + } + +-/* Delete and set the location part of variable MEM_EXPR (LOC) +- in dataflow set SET to LOC. ++/* Set the location part of variable MEM_EXPR (LOC) in dataflow set ++ SET to LOC. + Adjust the address first if it is stack pointer based. */ + + static void +-var_mem_delete_and_set (dataflow_set *set, rtx loc) ++var_mem_set (dataflow_set *set, rtx loc) + { + tree decl = MEM_EXPR (loc); + HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0; +@@ -867,6 +884,16 @@ var_mem_delete_and_set (dataflow_set *se + set_variable_part (set, loc, decl, offset); + } + ++/* Delete and set the location part of variable MEM_EXPR (LOC) ++ in dataflow set SET to LOC. ++ Adjust the address first if it is stack pointer based. */ ++ ++static void ++var_mem_delete_and_set (dataflow_set *set, rtx loc) ++{ ++ var_mem_set (set, loc); ++} ++ + /* Delete the location part LOC from dataflow set SET. + Adjust the address first if it is stack pointer based. */ + +@@ -1547,7 +1574,7 @@ add_stores (rtx loc, rtx expr, void *ins + && track_expr_p (REG_EXPR (loc))) + ? MO_SET : MO_CLOBBER); + mo->u.loc = loc; +- mo->insn = (rtx) insn; ++ mo->insn = NEXT_INSN ((rtx) insn); + } + else if (GET_CODE (loc) == MEM + && MEM_EXPR (loc) +@@ -1558,7 +1585,7 @@ add_stores (rtx loc, rtx expr, void *ins + + mo->type = GET_CODE (expr) == CLOBBER ? MO_CLOBBER : MO_SET; + mo->u.loc = loc; +- mo->insn = (rtx) insn; ++ mo->insn = NEXT_INSN ((rtx) insn); + } + } + +@@ -1589,6 +1616,16 @@ compute_bb_dataflow (basic_block bb) + break; + + case MO_USE: ++ { ++ rtx loc = VTI (bb)->mos[i].u.loc; ++ ++ if (GET_CODE (loc) == REG) ++ var_reg_set (out, loc); ++ else if (GET_CODE (loc) == MEM) ++ var_mem_set (out, loc); ++ } ++ break; ++ + case MO_SET: + { + rtx loc = VTI (bb)->mos[i].u.loc; +@@ -2364,6 +2401,18 @@ emit_notes_in_bb (basic_block bb) + break; + + case MO_USE: ++ { ++ rtx loc = VTI (bb)->mos[i].u.loc; ++ ++ if (GET_CODE (loc) == REG) ++ var_reg_set (&set, loc); ++ else ++ var_mem_set (&set, loc); ++ ++ emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); ++ } ++ break; ++ + case MO_SET: + { + rtx loc = VTI (bb)->mos[i].u.loc; +@@ -2373,10 +2422,7 @@ emit_notes_in_bb (basic_block bb) + else + var_mem_delete_and_set (&set, loc); + +- if (VTI (bb)->mos[i].type == MO_USE) +- emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); +- else +- emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); ++ emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); + } + break; + +@@ -2391,9 +2437,9 @@ emit_notes_in_bb (basic_block bb) + var_mem_delete (&set, loc); + + if (VTI (bb)->mos[i].type == MO_USE_NO_VAR) +- emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); +- else + emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); ++ else ++ emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); + } + break; + +@@ -2616,15 +2662,18 @@ vt_initialize (void) + } + + n1 = VTI (bb)->n_mos; ++ /* This will record NEXT_INSN (insn), such that we can ++ insert notes before it without worrying about any ++ notes that MO_USEs might emit after the insn. */ + note_stores (PATTERN (insn), add_stores, insn); + n2 = VTI (bb)->n_mos - 1; + +- /* Order the MO_SETs to be before MO_CLOBBERs. */ ++ /* Order the MO_CLOBBERs to be before MO_SETs. */ + while (n1 < n2) + { +- while (n1 < n2 && VTI (bb)->mos[n1].type == MO_SET) ++ while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER) + n1++; +- while (n1 < n2 && VTI (bb)->mos[n2].type == MO_CLOBBER) ++ while (n1 < n2 && VTI (bb)->mos[n2].type == MO_SET) + n2--; + if (n1 < n2) + { diff --git a/SOURCES/gcc34-var-tracking-coalesce.patch b/SOURCES/gcc34-var-tracking-coalesce.patch new file mode 100644 index 0000000..c856e27 --- /dev/null +++ b/SOURCES/gcc34-var-tracking-coalesce.patch @@ -0,0 +1,728 @@ +2006-12-08 Jakub Jelinek + + * g++.dg/debug/vartrack1.C: New test. + +2006-09-11 Alexandre Oliva + + PR target/28672 + * var-tracking.c (dump_dataflow_set): Start dumping at + register zero. + (clobber_variable_part): Kill only the variable part in + registers holding it, leaving other variables alone. + +2006-08-09 Alexandre Oliva + + * var-tracking.c (enum micro_operation_type): Add MO_COPY. + (var_debug_decl): New function. + (var_reg_set): Follow debug decl link. Add location even if + reg is already known to hold some other variable. + (var_mem_set): Follow debug decl link. + (var_reg_delete_and_set, var_mem_delete_and_set): Follow debug + decl link. Delete other known locations of the variable part + if requested. + (var_reg_delete, var_mem_delete): Delete other known locations + of the variable part if requested. + (same_variable_part_p): New function. + (add_stores): Select MO_COPY when appropriate. + (vt_initialize): Handle it. + (compute_bb_dataflow, emit_notes_in_bb): Likewise. Delete + known locations for MO_SET and MO_CLOBBER. + (find_variable_location_part): New function. + (set_variable_part, delete_variable_part): Use it. + (clobber_variable_part): New function. + +--- gcc/var-tracking.c.orig 2006-12-08 02:14:36.000000000 -0200 ++++ gcc/var-tracking.c 2006-12-08 02:14:51.000000000 -0200 +@@ -112,6 +112,8 @@ enum micro_operation_type + MO_USE_NO_VAR,/* Use location which is not associated with a variable + or the variable is not trackable. */ + MO_SET, /* Set location. */ ++ MO_COPY, /* Copy the same portion of a variable from one ++ loation to another. */ + MO_CLOBBER, /* Clobber location. */ + MO_CALL, /* Call insn. */ + MO_ADJUST /* Adjust stack pointer. */ +@@ -293,13 +295,14 @@ static void vars_clear (htab_t); + static variable unshare_variable (dataflow_set *set, variable var); + static int vars_copy_1 (void **, void *); + static void vars_copy (htab_t, htab_t); ++static tree var_debug_decl (tree); + static void var_reg_set (dataflow_set *, rtx); +-static void var_reg_delete_and_set (dataflow_set *, rtx); +-static void var_reg_delete (dataflow_set *, rtx); ++static void var_reg_delete_and_set (dataflow_set *, rtx, bool); ++static void var_reg_delete (dataflow_set *, rtx, bool); + static void var_regno_delete (dataflow_set *, int); + static void var_mem_set (dataflow_set *, rtx); +-static void var_mem_delete_and_set (dataflow_set *, rtx); +-static void var_mem_delete (dataflow_set *, rtx); ++static void var_mem_delete_and_set (dataflow_set *, rtx, bool); ++static void var_mem_delete (dataflow_set *, rtx, bool); + + static void dataflow_set_init (dataflow_set *, int); + static void dataflow_set_clear (dataflow_set *); +@@ -316,6 +319,7 @@ static void dataflow_set_destroy (datafl + + static bool contains_symbol_ref (rtx); + static bool track_expr_p (tree); ++static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT); + static int count_uses (rtx *, void *); + static void count_uses_1 (rtx *, void *); + static void count_stores (rtx, rtx, void *); +@@ -333,6 +337,7 @@ static void dump_dataflow_sets (void); + + static void variable_was_changed (variable, htab_t); + static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); ++static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); + static void delete_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT); + static int emit_note_insn_var_location (void **, void *); + static void emit_notes_for_changes (rtx, enum emit_note_where); +@@ -794,6 +799,14 @@ vars_copy (htab_t dst, htab_t src) + htab_traverse (src, vars_copy_1, dst); + } + ++/* Map a decl to its main debug decl. */ ++ ++static inline tree ++var_debug_decl (tree decl) ++{ ++ return decl; ++} ++ + /* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ + + static void +@@ -801,23 +814,35 @@ var_reg_set (dataflow_set *set, rtx loc) + { + tree decl = REG_EXPR (loc); + HOST_WIDE_INT offset = REG_OFFSET (loc); ++ attrs node; ++ ++ decl = var_debug_decl (decl); + +- if (set->regs[REGNO (loc)] == NULL) ++ for (node = set->regs[REGNO (loc)]; node; node = node->next) ++ if (node->decl == decl && node->offset == offset) ++ break; ++ if (!node) + attrs_list_insert (&set->regs[REGNO (loc)], decl, offset, loc); + set_variable_part (set, loc, decl, offset); + } + +-/* Delete current content of register LOC in dataflow set SET +- and set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */ ++/* Delete current content of register LOC in dataflow set SET and set ++ the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). If ++ MODIFY is true, any other live copies of the same variable part are ++ also deleted from the dataflow set, otherwise the variable part is ++ assumed to be copied from another location holding the same ++ part. */ + + static void +-var_reg_delete_and_set (dataflow_set *set, rtx loc) ++var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify) + { + tree decl = REG_EXPR (loc); + HOST_WIDE_INT offset = REG_OFFSET (loc); + attrs node, next; + attrs *nextp; + ++ decl = var_debug_decl (decl); ++ + nextp = &set->regs[REGNO (loc)]; + for (node = *nextp; node; node = next) + { +@@ -834,17 +859,31 @@ var_reg_delete_and_set (dataflow_set *se + nextp = &node->next; + } + } ++ if (modify) ++ clobber_variable_part (set, loc, decl, offset); + var_reg_set (set, loc); + } + +-/* Delete current content of register LOC in dataflow set SET. */ ++/* Delete current content of register LOC in dataflow set SET. If ++ CLOBBER is true, also delete any other live copies of the same ++ variable part. */ + + static void +-var_reg_delete (dataflow_set *set, rtx loc) ++var_reg_delete (dataflow_set *set, rtx loc, bool clobber) + { + attrs *reg = &set->regs[REGNO (loc)]; + attrs node, next; + ++ if (clobber) ++ { ++ tree decl = REG_EXPR (loc); ++ HOST_WIDE_INT offset = REG_OFFSET (loc); ++ ++ decl = var_debug_decl (decl); ++ ++ clobber_variable_part (set, NULL, decl, offset); ++ } ++ + for (node = *reg; node; node = next) + { + next = node->next; +@@ -881,28 +920,44 @@ var_mem_set (dataflow_set *set, rtx loc) + tree decl = MEM_EXPR (loc); + HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0; + ++ decl = var_debug_decl (decl); ++ + set_variable_part (set, loc, decl, offset); + } + +-/* Delete and set the location part of variable MEM_EXPR (LOC) +- in dataflow set SET to LOC. ++/* Delete and set the location part of variable MEM_EXPR (LOC) in ++ dataflow set SET to LOC. If MODIFY is true, any other live copies ++ of the same variable part are also deleted from the dataflow set, ++ otherwise the variable part is assumed to be copied from another ++ location holding the same part. + Adjust the address first if it is stack pointer based. */ + + static void +-var_mem_delete_and_set (dataflow_set *set, rtx loc) ++var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify) + { ++ tree decl = MEM_EXPR (loc); ++ HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0; ++ ++ decl = var_debug_decl (decl); ++ ++ if (modify) ++ clobber_variable_part (set, NULL, decl, offset); + var_mem_set (set, loc); + } + +-/* Delete the location part LOC from dataflow set SET. ++/* Delete the location part LOC from dataflow set SET. If CLOBBER is ++ true, also delete any other live copies of the same variable part. + Adjust the address first if it is stack pointer based. */ + + static void +-var_mem_delete (dataflow_set *set, rtx loc) ++var_mem_delete (dataflow_set *set, rtx loc, bool clobber) + { + tree decl = MEM_EXPR (loc); + HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0; + ++ decl = var_debug_decl (decl); ++ if (clobber) ++ clobber_variable_part (set, NULL, decl, offset); + delete_variable_part (set, loc, decl, offset); + } + +@@ -1476,6 +1531,41 @@ track_expr_p (tree expr) + return 1; + } + ++/* Determine whether a given LOC refers to the same variable part as ++ EXPR+OFFSET. */ ++ ++static bool ++same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset) ++{ ++ tree expr2; ++ HOST_WIDE_INT offset2; ++ ++ if (! DECL_P (expr)) ++ return false; ++ ++ if (GET_CODE (loc) == REG) ++ { ++ expr2 = REG_EXPR (loc); ++ offset2 = REG_OFFSET (loc); ++ } ++ else if (GET_CODE (loc) == MEM) ++ { ++ expr2 = MEM_EXPR (loc); ++ offset2 = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0; ++ } ++ else ++ return false; ++ ++ if (! expr2 || ! DECL_P (expr2)) ++ return false; ++ ++ expr = var_debug_decl (expr); ++ expr2 = var_debug_decl (expr2); ++ ++ return (expr == expr2 && offset == offset2); ++} ++ ++ + /* Count uses (register and memory references) LOC which will be tracked. + INSN is instruction which the LOC is part of. */ + +@@ -1570,9 +1660,18 @@ add_stores (rtx loc, rtx expr, void *ins + basic_block bb = BLOCK_FOR_INSN ((rtx) insn); + micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; + +- mo->type = ((GET_CODE (expr) != CLOBBER && REG_EXPR (loc) +- && track_expr_p (REG_EXPR (loc))) +- ? MO_SET : MO_CLOBBER); ++ if (GET_CODE (expr) == CLOBBER ++ || ! REG_EXPR (loc) ++ || ! track_expr_p (REG_EXPR (loc))) ++ mo->type = MO_CLOBBER; ++ else if (GET_CODE (expr) == SET ++ && SET_DEST (expr) == loc ++ && same_variable_part_p (SET_SRC (expr), ++ REG_EXPR (loc), ++ REG_OFFSET (loc))) ++ mo->type = MO_COPY; ++ else ++ mo->type = MO_SET; + mo->u.loc = loc; + mo->insn = NEXT_INSN ((rtx) insn); + } +@@ -1583,7 +1682,17 @@ add_stores (rtx loc, rtx expr, void *ins + basic_block bb = BLOCK_FOR_INSN ((rtx) insn); + micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++; + +- mo->type = GET_CODE (expr) == CLOBBER ? MO_CLOBBER : MO_SET; ++ if (GET_CODE (expr) == CLOBBER) ++ mo->type = MO_CLOBBER; ++ else if (GET_CODE (expr) == SET ++ && SET_DEST (expr) == loc ++ && same_variable_part_p (SET_SRC (expr), ++ MEM_EXPR (loc), ++ MEM_OFFSET (loc) ++ ? INTVAL (MEM_OFFSET (loc)) : 0)) ++ mo->type = MO_COPY; ++ else ++ mo->type = MO_SET; + mo->u.loc = loc; + mo->insn = NEXT_INSN ((rtx) insn); + } +@@ -1631,21 +1740,42 @@ compute_bb_dataflow (basic_block bb) + rtx loc = VTI (bb)->mos[i].u.loc; + + if (GET_CODE (loc) == REG) +- var_reg_delete_and_set (out, loc); ++ var_reg_delete_and_set (out, loc, true); + else if (GET_CODE (loc) == MEM) +- var_mem_delete_and_set (out, loc); ++ var_mem_delete_and_set (out, loc, true); ++ } ++ break; ++ ++ case MO_COPY: ++ { ++ rtx loc = VTI (bb)->mos[i].u.loc; ++ ++ if (GET_CODE (loc) == REG) ++ var_reg_delete_and_set (out, loc, false); ++ else if (GET_CODE (loc) == MEM) ++ var_mem_delete_and_set (out, loc, false); + } + break; + + case MO_USE_NO_VAR: ++ { ++ rtx loc = VTI (bb)->mos[i].u.loc; ++ ++ if (GET_CODE (loc) == REG) ++ var_reg_delete (out, loc, false); ++ else if (GET_CODE (loc) == MEM) ++ var_mem_delete (out, loc, false); ++ } ++ break; ++ + case MO_CLOBBER: + { + rtx loc = VTI (bb)->mos[i].u.loc; + + if (GET_CODE (loc) == REG) +- var_reg_delete (out, loc); ++ var_reg_delete (out, loc, true); + else if (GET_CODE (loc) == MEM) +- var_mem_delete (out, loc); ++ var_mem_delete (out, loc, true); + } + break; + +@@ -1824,7 +1954,7 @@ dump_dataflow_set (dataflow_set *set) + + fprintf (rtl_dump_file, "Stack adjustment: " HOST_WIDE_INT_PRINT_DEC "\n", + set->stack_adjust); +- for (i = 1; i < FIRST_PSEUDO_REGISTER; i++) ++ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + if (set->regs[i]) + { +@@ -1905,6 +2035,39 @@ variable_was_changed (variable var, htab + } + } + ++/* Look for the index in VAR->var_part corresponding to OFFSET. ++ Return -1 if not found. If INSERTION_POINT is non-NULL, the ++ referenced int will be set to the index that the part has or should ++ have, if it should be inserted. */ ++ ++static inline int ++find_variable_location_part (variable var, HOST_WIDE_INT offset, ++ int *insertion_point) ++{ ++ int pos, low, high; ++ ++ /* Find the location part. */ ++ low = 0; ++ high = var->n_var_parts; ++ while (low != high) ++ { ++ pos = (low + high) / 2; ++ if (var->var_part[pos].offset < offset) ++ low = pos + 1; ++ else ++ high = pos; ++ } ++ pos = low; ++ ++ if (insertion_point) ++ *insertion_point = pos; ++ ++ if (pos < var->n_var_parts && var->var_part[pos].offset == offset) ++ return pos; ++ ++ return -1; ++} ++ + /* Set the part of variable's location in the dataflow set SET. The variable + part is specified by variable's declaration DECL and offset OFFSET and the + part's location by LOC. */ +@@ -1912,7 +2075,7 @@ variable_was_changed (variable var, htab + static void + set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset) + { +- int pos, low, high; ++ int pos; + location_chain node, next; + location_chain *nextp; + variable var; +@@ -1935,22 +2098,13 @@ set_variable_part (dataflow_set *set, rt + } + else + { ++ int inspos = 0; ++ + var = (variable) *slot; + +- /* Find the location part. */ +- low = 0; +- high = var->n_var_parts; +- while (low != high) +- { +- pos = (low + high) / 2; +- if (var->var_part[pos].offset < offset) +- low = pos + 1; +- else +- high = pos; +- } +- pos = low; ++ pos = find_variable_location_part (var, offset, &inspos); + +- if (pos < var->n_var_parts && var->var_part[pos].offset == offset) ++ if (pos >= 0) + { + node = var->var_part[pos].loc_chain; + +@@ -1985,10 +2139,10 @@ set_variable_part (dataflow_set *set, rt + abort (); + #endif + +- /* We have to move the elements of array starting at index low to the +- next position. */ +- for (high = var->n_var_parts; high > low; high--) +- var->var_part[high] = var->var_part[high - 1]; ++ /* We have to move the elements of array starting at index ++ inspos to the next position. */ ++ for (pos = var->n_var_parts; pos > inspos; pos--) ++ var->var_part[pos] = var->var_part[pos - 1]; + + var->n_var_parts++; + var->var_part[pos].offset = offset; +@@ -2028,6 +2182,67 @@ set_variable_part (dataflow_set *set, rt + } + } + ++/* Remove all recorded register locations for the given variable part ++ from dataflow set SET, except for those that are identical to loc. ++ The variable part is specified by variable's declaration DECL and ++ offset OFFSET. */ ++ ++static void ++clobber_variable_part (dataflow_set *set, rtx loc, tree decl, ++ HOST_WIDE_INT offset) ++{ ++ void **slot; ++ ++ if (! decl || ! DECL_P (decl)) ++ return; ++ ++ slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl), ++ NO_INSERT); ++ if (slot) ++ { ++ variable var = (variable) *slot; ++ int pos = find_variable_location_part (var, offset, NULL); ++ ++ if (pos >= 0) ++ { ++ location_chain node, next; ++ ++ /* Remove the register locations from the dataflow set. */ ++ next = var->var_part[pos].loc_chain; ++ for (node = next; node; node = next) ++ { ++ next = node->next; ++ if (node->loc != loc) ++ { ++ if (REG_P (node->loc)) ++ { ++ attrs anode, anext; ++ attrs *anextp; ++ ++ /* Remove the variable part from the register's ++ list, but preserve any other variable parts ++ that might be regarded as live in that same ++ register. */ ++ anextp = &set->regs[REGNO (node->loc)]; ++ for (anode = *anextp; anode; anode = anext) ++ { ++ anext = anode->next; ++ if (anode->decl == decl ++ && anode->offset == offset) ++ { ++ pool_free (attrs_pool, anode); ++ *anextp = anext; ++ } ++ } ++ } ++ ++ delete_variable_part (set, node->loc, decl, offset); ++ } ++ } ++ } ++ } ++} ++ + /* Delete the part of variable's location from dataflow set SET. The variable + part is specified by variable's declaration DECL and offset OFFSET and the + part's location by LOC. */ +@@ -2036,7 +2251,6 @@ static void + delete_variable_part (dataflow_set *set, rtx loc, tree decl, + HOST_WIDE_INT offset) + { +- int pos, low, high; + void **slot; + + slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl), +@@ -2044,21 +2258,9 @@ delete_variable_part (dataflow_set *set, + if (slot) + { + variable var = (variable) *slot; ++ int pos = find_variable_location_part (var, offset, NULL); + +- /* Find the location part. */ +- low = 0; +- high = var->n_var_parts; +- while (low != high) +- { +- pos = (low + high) / 2; +- if (var->var_part[pos].offset < offset) +- low = pos + 1; +- else +- high = pos; +- } +- pos = low; +- +- if (pos < var->n_var_parts && var->var_part[pos].offset == offset) ++ if (pos >= 0) + { + location_chain node, next; + location_chain *nextp; +@@ -2124,7 +2326,7 @@ delete_variable_part (dataflow_set *set, + } + } + if (changed) +- variable_was_changed (var, set->vars); ++ variable_was_changed (var, set->vars); + } + } + } +@@ -2418,28 +2620,50 @@ emit_notes_in_bb (basic_block bb) + rtx loc = VTI (bb)->mos[i].u.loc; + + if (GET_CODE (loc) == REG) +- var_reg_delete_and_set (&set, loc); ++ var_reg_delete_and_set (&set, loc, true); ++ else ++ var_mem_delete_and_set (&set, loc, true); ++ ++ emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); ++ } ++ break; ++ ++ case MO_COPY: ++ { ++ rtx loc = VTI (bb)->mos[i].u.loc; ++ ++ if (GET_CODE (loc) == REG) ++ var_reg_delete_and_set (&set, loc, false); + else +- var_mem_delete_and_set (&set, loc); ++ var_mem_delete_and_set (&set, loc, false); + + emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); + } + break; + + case MO_USE_NO_VAR: +- case MO_CLOBBER: + { + rtx loc = VTI (bb)->mos[i].u.loc; + + if (GET_CODE (loc) == REG) +- var_reg_delete (&set, loc); ++ var_reg_delete (&set, loc, false); + else +- var_mem_delete (&set, loc); ++ var_mem_delete (&set, loc, false); ++ ++ emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); ++ } ++ break; ++ ++ case MO_CLOBBER: ++ { ++ rtx loc = VTI (bb)->mos[i].u.loc; + +- if (VTI (bb)->mos[i].type == MO_USE_NO_VAR) +- emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); ++ if (GET_CODE (loc) == REG) ++ var_reg_delete (&set, loc, true); + else +- emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); ++ var_mem_delete (&set, loc, true); ++ ++ emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); + } + break; + +@@ -2673,7 +2897,8 @@ vt_initialize (void) + { + while (n1 < n2 && VTI (bb)->mos[n1].type == MO_CLOBBER) + n1++; +- while (n1 < n2 && VTI (bb)->mos[n2].type == MO_SET) ++ while (n1 < n2 && (VTI (bb)->mos[n2].type == MO_SET ++ || VTI (bb)->mos[n2].type == MO_COPY)) + n2--; + if (n1 < n2) + { +--- gcc/testsuite/g++.dg/debug/vartrack1.C 2004-06-24 14:04:38.000000000 -0400 ++++ gcc/testsuite/g++.dg/debug/vartrack1.C 2006-12-08 05:29:41.000000000 -0500 +@@ -0,0 +1,99 @@ ++// This testcase used to hang the compiler in vt_find_locations. ++// { dg-do compile } ++// { dg-options "-O2 -g" } ++ ++struct S ++{ ++ int a; ++ S *b, *c, *d; ++}; ++ ++struct T ++{ ++ void f1 (S *x); ++ void f2 (S *x); ++ void f3 (S *x, S *y); ++ S *e; ++}; ++ ++void ++T::f3 (S *x, S *y) ++{ ++ while (x != this->e && (!x || x->a == 1)) ++ { ++ if (x == y->c) ++ { ++ S *w = y->d; ++ if (w && w->a == 0) ++ { ++ w->a = 1; ++ y->a = 0; ++ f2 (y); ++ w = y->d; ++ } ++ if (w && (!w->c || w->c->a == 1) && (!w->d || w->d->a == 1)) ++ { ++ w->a = 0; ++ x = y; ++ y = x->b; ++ } ++ else ++ { ++ if (w && (!w->d || w->d->a == 1)) ++ { ++ if (w->c) ++ w->c->a = 1; ++ w->a = 0; ++ f1 (w); ++ w = y->d; ++ } ++ if (w) ++ { ++ w->a = y->a; ++ if (w->d) ++ w->d->a = 1; ++ } ++ y->a = 1; ++ f2 (y); ++ x = e; ++ } ++ } ++ else ++ { ++ S *w = y->c; ++ if (w && w->a == 0) ++ { ++ w->a = 1; ++ y->a = 0; ++ f1 (y); ++ w = y->c; ++ } ++ if (w && (!w->c || w->c->a == 1) && (!w->d || w->d->a == 1)) ++ { ++ w->a = 0; ++ x = y; ++ y = x->b; ++ } ++ else ++ { ++ if (w && (!w->c || w->c->a == 1)) ++ { ++ w->a = 0; ++ if (w->d) ++ w->d->a = 1; ++ f2 (w); ++ w = y->c; ++ } ++ if (w) ++ { ++ w->a = y->a; ++ if (w->c) ++ w->c->a = 1; ++ } ++ y->a = 1; ++ f1 (y); ++ x = e; ++ } ++ } ++ } ++} diff --git a/SOURCES/gcc34-var-tracking-fix.patch b/SOURCES/gcc34-var-tracking-fix.patch new file mode 100644 index 0000000..be2453d --- /dev/null +++ b/SOURCES/gcc34-var-tracking-fix.patch @@ -0,0 +1,299 @@ +2005-06-08 Eric Botcazou + + PR debug/21946 + * dwarf2out.c (add_loc_descr_op_piece): Move to the + DWARF2_DEBUGGING_INFO section. + +2005-06-07 Jakub Jelinek + + PR debug/21946 + * dwarf2out.c (add_loc_descr_op_piece): New function. + (multiple_reg_loc_descriptor, concat_loc_descriptor, + loc_descriptor): Use it. + + * var-tracking.c: Include regs.h and expr.h. + (emit_note_insn_var_location): Skip over pieces where offset + is smaller than previous offset plus previous piece mode size. + Optimize adjacent hard registers or memory locations. + * Makefile.in (var-tracking.o): Depend on $(REGS_H) and $(EXPR_H). + +--- gcc/dwarf2out.c.jj 2005-06-07 00:39:11.000000000 +0200 ++++ gcc/dwarf2out.c 2005-06-07 00:54:10.000000000 +0200 +@@ -3747,6 +3748,7 @@ static dw_die_ref subrange_type_die (tre + static dw_die_ref modified_type_die (tree, int, int, dw_die_ref); + static int type_is_enum (tree); + static unsigned int dbx_reg_number (rtx); ++static void add_loc_descr_op_piece (dw_loc_descr_ref *, int); + static dw_loc_descr_ref reg_loc_descriptor (rtx); + static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int); + static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx); +@@ -8176,6 +8178,26 @@ dbx_reg_number (rtx rtl) + return DBX_REGISTER_NUMBER (regno); + } + ++/* Optionally add a DW_OP_piece term to a location description expression. ++ DW_OP_piece is only added if the location description expression already ++ doesn't end with DW_OP_piece. */ ++ ++static void ++add_loc_descr_op_piece (dw_loc_descr_ref *list_head, int size) ++{ ++ dw_loc_descr_ref loc; ++ ++ if (*list_head != NULL) ++ { ++ /* Find the end of the chain. */ ++ for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next) ++ ; ++ ++ if (loc->dw_loc_opc != DW_OP_piece) ++ loc->dw_loc_next = new_loc_descr (DW_OP_piece, size, 0); ++ } ++} ++ + /* Return a location descriptor that designates a machine register or + zero if there is none. */ + +@@ -8235,7 +8257,7 @@ multiple_reg_loc_descriptor (rtx rtl, rt + + t = one_reg_loc_descriptor (reg); + add_loc_descr (&loc_result, t); +- add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0)); ++ add_loc_descr_op_piece (&loc_result, size); + ++reg; + } + return loc_result; +@@ -8256,7 +8278,7 @@ multiple_reg_loc_descriptor (rtx rtl, rt + t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i))); + add_loc_descr (&loc_result, t); + size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0))); +- add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0)); ++ add_loc_descr_op_piece (&loc_result, size); + } + return loc_result; + } +@@ -8551,14 +8573,10 @@ concat_loc_descriptor (rtx x0, rtx x1) + return 0; + + cc_loc_result = x0_ref; +- add_loc_descr (&cc_loc_result, +- new_loc_descr (DW_OP_piece, +- GET_MODE_SIZE (GET_MODE (x0)), 0)); ++ add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x0))); + + add_loc_descr (&cc_loc_result, x1_ref); +- add_loc_descr (&cc_loc_result, +- new_loc_descr (DW_OP_piece, +- GET_MODE_SIZE (GET_MODE (x1)), 0)); ++ add_loc_descr_op_piece (&cc_loc_result, GET_MODE_SIZE (GET_MODE (x1))); + + return cc_loc_result; + } +@@ -8619,8 +8637,7 @@ loc_descriptor (rtx rtl, bool can_use_fb + loc_result = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), + can_use_fbreg); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); +- add_loc_descr (&loc_result, +- new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); ++ add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode)); + for (i = 1; i < num_elem; i++) + { + dw_loc_descr_ref temp; +@@ -8629,9 +8646,7 @@ loc_descriptor (rtx rtl, bool can_use_fb + can_use_fbreg); + add_loc_descr (&loc_result, temp); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); +- add_loc_descr (&loc_result, +- new_loc_descr (DW_OP_piece, +- GET_MODE_SIZE (mode), 0)); ++ add_loc_descr_op_piece (&loc_result, GET_MODE_SIZE (mode)); + } + } + break; +@@ -9930,8 +9945,7 @@ add_location_or_const_value_attribute (d + /* Create the first one, so we have something to add to. */ + descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0), true); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); +- add_loc_descr (&descr, +- new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); ++ add_loc_descr_op_piece (&descr, GET_MODE_SIZE (mode)); + for (i = 1; i < num_elem; i++) + { + dw_loc_descr_ref temp; +@@ -9939,9 +9953,7 @@ add_location_or_const_value_attribute (d + temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0), true); + add_loc_descr (&descr, temp); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); +- add_loc_descr (&descr, +- new_loc_descr (DW_OP_piece, +- GET_MODE_SIZE (mode), 0)); ++ add_loc_descr_op_piece (&descr, GET_MODE_SIZE (mode)); + } + } + add_AT_location_description (die, DW_AT_location, descr); +--- gcc/var-tracking.c.jj 2005-06-07 00:39:11.000000000 +0200 ++++ gcc/var-tracking.c 2005-06-07 00:52:15.000000000 +0200 +@@ -102,6 +102,8 @@ + #include "alloc-pool.h" + #include "fibheap.h" + #include "hashtab.h" ++#include "regs.h" ++#include "expr.h" + + /* Type of micro operation. */ + enum micro_operation_type +@@ -2185,10 +2187,12 @@ emit_note_insn_var_location (void **varp + rtx insn = ((emit_note_data *)data)->insn; + enum emit_note_where where = ((emit_note_data *)data)->where; + rtx note; +- int i; ++ int i, j, n_var_parts; + bool complete; + HOST_WIDE_INT last_limit; + tree type_size_unit; ++ HOST_WIDE_INT offsets[MAX_VAR_PARTS]; ++ rtx loc[MAX_VAR_PARTS]; + + #ifdef ENABLE_CHECKING + if (!var->decl) +@@ -2197,16 +2201,90 @@ emit_note_insn_var_location (void **varp + + complete = true; + last_limit = 0; ++ n_var_parts = 0; + for (i = 0; i < var->n_var_parts; i++) + { ++ enum machine_mode mode, wider_mode; ++ + if (last_limit < var->var_part[i].offset) + { + complete = false; + break; + } +- last_limit +- = (var->var_part[i].offset +- + GET_MODE_SIZE (GET_MODE (var->var_part[i].loc_chain->loc))); ++ else if (last_limit > var->var_part[i].offset) ++ continue; ++ offsets[n_var_parts] = var->var_part[i].offset; ++ loc[n_var_parts] = var->var_part[i].loc_chain->loc; ++ mode = GET_MODE (loc[n_var_parts]); ++ last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); ++ ++ /* Attempt to merge adjacent registers or memory. */ ++ wider_mode = GET_MODE_WIDER_MODE (mode); ++ for (j = i + 1; j < var->n_var_parts; j++) ++ if (last_limit <= var->var_part[j].offset) ++ break; ++ if (j < var->n_var_parts ++ && wider_mode != VOIDmode ++ && GET_CODE (loc[n_var_parts]) ++ == GET_CODE (var->var_part[j].loc_chain->loc) ++ && mode == GET_MODE (var->var_part[j].loc_chain->loc) ++ && last_limit == var->var_part[j].offset) ++ { ++ rtx new_loc = NULL; ++ rtx loc2 = var->var_part[j].loc_chain->loc; ++ ++ if (REG_P (loc[n_var_parts]) ++ && HARD_REGNO_NREGS (REGNO (loc[n_var_parts]), mode) * 2 ++ == HARD_REGNO_NREGS (REGNO (loc[n_var_parts]), wider_mode) ++ && REGNO (loc[n_var_parts]) ++ + HARD_REGNO_NREGS (REGNO (loc[n_var_parts]), mode) ++ == REGNO (loc2)) ++ { ++ if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN) ++ new_loc = simplify_subreg (wider_mode, loc[n_var_parts], ++ mode, 0); ++ else if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN) ++ new_loc = simplify_subreg (wider_mode, loc2, mode, 0); ++ if (new_loc) ++ { ++ if (!REG_P (new_loc) ++ || REGNO (new_loc) != REGNO (loc[n_var_parts])) ++ new_loc = NULL; ++ else ++ REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]); ++ } ++ } ++ else if (GET_CODE (loc[n_var_parts]) == MEM ++ && GET_CODE (XEXP (loc2, 0)) == PLUS ++ && GET_CODE (XEXP (XEXP (loc2, 0), 0)) == REG ++ && GET_CODE (XEXP (XEXP (loc2, 0), 1)) == CONST_INT) ++ { ++ if ((GET_CODE (XEXP (loc[n_var_parts], 0)) == REG ++ && rtx_equal_p (XEXP (loc[n_var_parts], 0), ++ XEXP (XEXP (loc2, 0), 0)) ++ && INTVAL (XEXP (XEXP (loc2, 0), 1)) ++ == GET_MODE_SIZE (mode)) ++ || (GET_CODE (XEXP (loc[n_var_parts], 0)) == PLUS ++ && GET_CODE (XEXP (XEXP (loc[n_var_parts], 0), 1)) ++ == CONST_INT ++ && rtx_equal_p (XEXP (XEXP (loc[n_var_parts], 0), 0), ++ XEXP (XEXP (loc2, 0), 0)) ++ && INTVAL (XEXP (XEXP (loc[n_var_parts], 0), 1)) ++ + GET_MODE_SIZE (mode) ++ == INTVAL (XEXP (XEXP (loc2, 0), 1)))) ++ new_loc = adjust_address_nv (loc[n_var_parts], ++ wider_mode, 0); ++ } ++ ++ if (new_loc) ++ { ++ loc[n_var_parts] = new_loc; ++ mode = wider_mode; ++ last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode); ++ i = j; ++ } ++ } ++ ++n_var_parts; + } + type_size_unit = TYPE_SIZE_UNIT (TREE_TYPE (var->decl)); + if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit)) +@@ -2222,26 +2300,24 @@ emit_note_insn_var_location (void **varp + NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, + NULL_RTX); + } +- else if (var->n_var_parts == 1) ++ else if (n_var_parts == 1) + { + rtx expr_list +- = gen_rtx_EXPR_LIST (VOIDmode, +- var->var_part[0].loc_chain->loc, +- GEN_INT (var->var_part[0].offset)); ++ = gen_rtx_EXPR_LIST (VOIDmode, loc[0], GEN_INT (offsets[0])); + + NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, + expr_list); + } +- else if (var->n_var_parts) ++ else if (n_var_parts) + { +- rtx argp[MAX_VAR_PARTS]; + rtx parallel; + +- for (i = 0; i < var->n_var_parts; i++) +- argp[i] = gen_rtx_EXPR_LIST (VOIDmode, var->var_part[i].loc_chain->loc, +- GEN_INT (var->var_part[i].offset)); ++ for (i = 0; i < n_var_parts; i++) ++ loc[i] ++ = gen_rtx_EXPR_LIST (VOIDmode, loc[i], GEN_INT (offsets[i])); ++ + parallel = gen_rtx_PARALLEL (VOIDmode, +- gen_rtvec_v (var->n_var_parts, argp)); ++ gen_rtvec_v (n_var_parts, loc)); + NOTE_VAR_LOCATION (note) = gen_rtx_VAR_LOCATION (VOIDmode, var->decl, + parallel); + } +--- gcc/Makefile.in.jj 2005-06-07 00:39:11.000000000 +0200 ++++ gcc/Makefile.in 2005-06-07 00:55:12.000000000 +0200 +@@ -1693,7 +1693,8 @@ df.o : df.c $(CONFIG_H) $(SYSTEM_H) core + $(BASIC_BLOCK_H) df.h $(FIBHEAP_H) + var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ + $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h flags.h \ +- $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) ++ $(BASIC_BLOCK_H) output.h sbitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \ ++ $(REGS_H) $(EXPR_H) + conflict.o : conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(OBSTACK_H) \ + $(HASHTAB_H) $(RTL_H) hard-reg-set.h $(BASIC_BLOCK_H) + profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ diff --git a/SOURCES/gcc34-vsb-stack.patch b/SOURCES/gcc34-vsb-stack.patch new file mode 100644 index 0000000..30fc28b --- /dev/null +++ b/SOURCES/gcc34-vsb-stack.patch @@ -0,0 +1,315 @@ +2005-07-22 Jakub Jelinek + + PR middle-end/20303 + * c-pragma.c: Include varray.h. + (visibility_stack): New variable. + (handle_pragma_visibility): Use VARRAY. + * Makefile.in (c-pragma.o): Depend on varray.h. + * doc/invoke.texi: Remove the nested visibility push limit. + + * gcc.dg/visibility-d.c: New test. + +--- gcc/Makefile.in.jj 2005-07-21 15:31:14.000000000 +0200 ++++ gcc/Makefile.in 2005-07-22 11:20:35.000000000 +0200 +@@ -1345,7 +1345,8 @@ c-aux-info.o : c-aux-info.c $(CONFIG_H) + c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ + flags.h toplev.h $(C_COMMON_H) real.h + c-pragma.o: c-pragma.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \ +- function.h c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H) gt-c-pragma.h ++ function.h c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H) \ ++ varray.h gt-c-pragma.h + graph.o: graph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h flags.h output.h \ + $(RTL_H) function.h hard-reg-set.h $(BASIC_BLOCK_H) graph.h + sbitmap.o: sbitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h \ +--- gcc/doc/invoke.texi.jj 2005-06-07 00:39:11.000000000 +0200 ++++ gcc/doc/invoke.texi 2005-07-22 12:03:55.000000000 +0200 +@@ -11418,8 +11418,8 @@ For those adding visibility support to e + @samp{#pragma GCC visibility} of use. This works by you enclosing + the declarations you wish to set visibility for with (for example) + @samp{#pragma GCC visibility push(hidden)} and +-@samp{#pragma GCC visibility pop}. These can be nested up to sixteen +-times. Bear in mind that symbol visibility should be viewed @strong{as ++@samp{#pragma GCC visibility pop}. ++Bear in mind that symbol visibility should be viewed @strong{as + part of the API interface contract} and thus all new code should + always specify visibility when it is not the default ie; declarations + only for use within the local DSO should @strong{always} be marked explicitly +--- gcc/c-pragma.c.jj 2004-09-01 18:16:57.000000000 +0200 ++++ gcc/c-pragma.c 2005-07-22 11:42:24.000000000 +0200 +@@ -34,6 +34,7 @@ Software Foundation, 59 Temple Place - S + #include "c-common.h" + #include "output.h" + #include "tm_p.h" ++#include "varray.h" + + #define GCC_BAD(msgid) do { warning (msgid); return; } while (0) + #define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0) +@@ -483,6 +484,8 @@ maybe_apply_renaming_pragma (tree decl, + + + #ifdef HANDLE_PRAGMA_VISIBILITY ++static GTY(()) varray_type visibility_stack; ++ + static void handle_pragma_visibility (cpp_reader *); + + /* Sets the default visibility for symbols to something other than that +@@ -490,11 +493,13 @@ static void handle_pragma_visibility (cp + static void + handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED) + { /* Form is #pragma GCC visibility push(hidden)|pop */ +- static int visstack [16], visidx; + tree x; + enum cpp_ttype token; + enum { bad, push, pop } action = bad; + ++ if (!visibility_stack) ++ VARRAY_INT_INIT (visibility_stack, 32, "visibility_stack"); ++ + token = c_lex (&x); + if (token == CPP_NAME) + { +@@ -510,14 +515,17 @@ handle_pragma_visibility (cpp_reader *du + { + if (pop == action) + { +- if (!visidx) ++ int visidx = VARRAY_ACTIVE_SIZE (visibility_stack); ++ ++ if (visidx <= 0) + { + GCC_BAD ("No matching push for '#pragma GCC visibility pop'"); + } + else + { +- default_visibility = visstack[--visidx]; +- visibility_options.inpragma = (visidx>0); ++ default_visibility = VARRAY_INT (visibility_stack, visidx - 1); ++ VARRAY_POP (visibility_stack); ++ visibility_options.inpragma = (visidx>1); + } + } + else +@@ -529,14 +537,10 @@ handle_pragma_visibility (cpp_reader *du + { + GCC_BAD ("malformed #pragma GCC visibility push"); + } +- else if (visidx >= 16) +- { +- GCC_BAD ("No more than sixteen #pragma GCC visibility pushes allowed at once"); +- } + else + { + const char *str = IDENTIFIER_POINTER (x); +- visstack[visidx++] = default_visibility; ++ VARRAY_PUSH_INT (visibility_stack, (int) default_visibility); + if (!strcmp (str, "default")) + default_visibility = VISIBILITY_DEFAULT; + else if (!strcmp (str, "internal")) +--- gcc/testsuite/gcc.dg/visibility-d.c.jj 2005-07-22 11:28:44.000000000 +0200 ++++ gcc/testsuite/gcc.dg/visibility-d.c 2005-07-22 11:59:35.000000000 +0200 +@@ -0,0 +1,205 @@ ++/* PR middle-end/20303 */ ++/* Test nesting of #pragma GCC visibility. */ ++/* { dg-do compile } */ ++/* { dg-require-visibility "" } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo00" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo01" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo02" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo03" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo04" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo05" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo06" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo07" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo08" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo09" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo10" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo11" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo12" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo13" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo14" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo15" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo16" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo17" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo18" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo19" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo20" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo21" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo22" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo23" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo24" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo25" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo26" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo27" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo28" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo29" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo30" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo31" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo32" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo33" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo34" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo35" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo36" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo37" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo38" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo39" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo40" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo41" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo42" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo43" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo44" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo45" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo46" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo47" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo48" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo49" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo50" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo51" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo52" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo53" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo54" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo55" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo56" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo57" } } */ ++/* { dg-final { scan-assembler-not "\\.hidden\[^\\n\]foo58" } } */ ++/* { dg-final { scan-assembler "\\.hidden\[^\\n\]foo59" } } */ ++ ++#pragma GCC visibility push(default) ++void foo00(); ++#pragma GCC visibility push(hidden) ++void foo01(); ++#pragma GCC visibility push(default) ++void foo02(); ++#pragma GCC visibility push(hidden) ++void foo03(); ++#pragma GCC visibility push(default) ++void foo04(); ++#pragma GCC visibility push(default) ++void foo05(); ++#pragma GCC visibility push(default) ++void foo06(); ++#pragma GCC visibility push(hidden) ++void foo07(); ++#pragma GCC visibility push(default) ++void foo08(); ++#pragma GCC visibility push(hidden) ++void foo09(); ++#pragma GCC visibility push(default) ++void foo10(); ++#pragma GCC visibility push(hidden) ++void foo11(); ++#pragma GCC visibility push(hidden) ++void foo12(); ++#pragma GCC visibility push(hidden) ++void foo13(); ++#pragma GCC visibility push(default) ++void foo14(); ++#pragma GCC visibility push(hidden) ++void foo15(); ++#pragma GCC visibility push(default) ++void foo16(); ++#pragma GCC visibility push(hidden) ++void foo17(); ++#pragma GCC visibility push(default) ++void foo18(); ++#pragma GCC visibility push(hidden) ++void foo19(); ++#pragma GCC visibility push(default) ++void foo20(); ++#pragma GCC visibility push(hidden) ++void foo21(); ++#pragma GCC visibility push(default) ++void foo22(); ++#pragma GCC visibility push(hidden) ++void foo23(); ++#pragma GCC visibility push(default) ++void foo24(); ++#pragma GCC visibility push(hidden) ++void foo25(); ++#pragma GCC visibility push(default) ++void foo26(); ++#pragma GCC visibility push(hidden) ++void foo27(); ++#pragma GCC visibility push(default) ++void foo28(); ++#pragma GCC visibility push(hidden) ++void foo29(); ++#pragma GCC visibility pop ++void foo30(); ++#pragma GCC visibility pop ++void foo31(); ++#pragma GCC visibility pop ++void foo32(); ++#pragma GCC visibility pop ++void foo33(); ++#pragma GCC visibility pop ++void foo34(); ++#pragma GCC visibility pop ++void foo35(); ++#pragma GCC visibility pop ++void foo36(); ++#pragma GCC visibility pop ++void foo37(); ++#pragma GCC visibility pop ++void foo38(); ++#pragma GCC visibility pop ++void foo39(); ++#pragma GCC visibility pop ++void foo40(); ++#pragma GCC visibility pop ++void foo41(); ++#pragma GCC visibility pop ++void foo42(); ++#pragma GCC visibility pop ++void foo43(); ++#pragma GCC visibility pop ++void foo44(); ++#pragma GCC visibility pop ++void foo45(); ++#pragma GCC visibility pop ++void foo46(); ++#pragma GCC visibility pop ++void foo47(); ++#pragma GCC visibility pop ++void foo48(); ++#pragma GCC visibility pop ++void foo49(); ++#pragma GCC visibility pop ++void foo50(); ++#pragma GCC visibility pop ++void foo51(); ++#pragma GCC visibility pop ++void foo52(); ++#pragma GCC visibility pop ++void foo53(); ++#pragma GCC visibility pop ++void foo54(); ++#pragma GCC visibility pop ++void foo55(); ++#pragma GCC visibility pop ++void foo56(); ++#pragma GCC visibility pop ++void foo57(); ++#pragma GCC visibility pop ++void foo58(); ++#pragma GCC visibility push (hidden) ++void foo59(); ++#pragma GCC visibility pop ++#pragma GCC visibility pop ++ ++#define D(N) \ ++void foo##N##0() { } \ ++void foo##N##1() { } \ ++void foo##N##2() { } \ ++void foo##N##3() { } \ ++void foo##N##4() { } \ ++void foo##N##5() { } \ ++void foo##N##6() { } \ ++void foo##N##7() { } \ ++void foo##N##8() { } \ ++void foo##N##9() { } ++D(0) ++D(1) ++D(2) ++D(3) ++D(4) ++D(5) diff --git a/SOURCES/gcc34-weakref.patch b/SOURCES/gcc34-weakref.patch new file mode 100644 index 0000000..8cff2c1 --- /dev/null +++ b/SOURCES/gcc34-weakref.patch @@ -0,0 +1,904 @@ +2005-11-16 Alexandre Oliva + + * c-common.c (handle_weakref_attribute): New. + (c_common_attribute_table): Add weakref. + * defaults.h (ASM_OUTPUT_WEAKREF): Define. + * doc/extend.texi: Document weakref attribute. + * varasm.c (do_assemble_alias): Handle weakrefs. + (finish_aliases_1): Do not reject weakrefs to external symbols. + * gthr-posix.h: Define __gthrw. For all identifiers that + might be weak, introduce weakrefs or non-weak aliases with + __gthrw, and prefix all uses with __ghtrw. + * config/rs6000/rs6000.h (ASM_OUTPUT_WEAKREF): Define. + + * g++.old-deja/g++.ext/weakref1.C: New test. + * g++.old-deja/g++.ext/weakref1a.cc: New helper file. + + * thr-objc.c (_XOPEN_SOURCE): Define. + +--- gcc/c-common.c.orig 2005-11-15 19:54:00.000000000 -0200 ++++ gcc/c-common.c 2005-11-15 19:54:02.000000000 -0200 +@@ -753,6 +753,7 @@ + static tree handle_aligned_attribute (tree *, tree, tree, int, bool *); + static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; + static tree handle_alias_attribute (tree *, tree, tree, int, bool *); ++static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ; + static tree handle_visibility_attribute (tree *, tree, tree, int, + bool *); + static tree handle_tls_model_attribute (tree *, tree, tree, int, +@@ -825,6 +826,8 @@ + handle_weak_attribute }, + { "alias", 1, 1, true, false, false, + handle_alias_attribute }, ++ { "weakref", 0, 1, true, false, false, ++ handle_weakref_attribute }, + { "no_instrument_function", 0, 0, true, false, false, + handle_no_instrument_function_attribute }, + { "malloc", 0, 0, true, false, false, +@@ -4988,7 +4991,12 @@ + if (TREE_CODE (decl) == FUNCTION_DECL) + DECL_INITIAL (decl) = error_mark_node; + else +- DECL_EXTERNAL (decl) = 0; ++ { ++ if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) ++ DECL_EXTERNAL (decl) = 1; ++ else ++ DECL_EXTERNAL (decl) = 0; ++ } + } + else + { +@@ -4999,6 +5007,40 @@ + return NULL_TREE; + } + ++/* Handle a "weakref" attribute; arguments as in struct ++ attribute_spec.handler. */ ++ ++static tree ++handle_weakref_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args, ++ int flags, bool *no_add_attrs) ++{ ++ tree attr = NULL_TREE; ++ ++ /* The idea here is that `weakref("name")' mutates into `weakref, ++ alias("name")', and weakref without arguments, in turn, ++ implicitly adds weak. */ ++ ++ if (args) ++ { ++ attr = tree_cons (get_identifier ("alias"), args, attr); ++ attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr); ++ ++ *no_add_attrs = true; ++ } ++ else ++ { ++ if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node))) ++ error ("%Jweakref attribute must appear before alias attribute", ++ *node); ++ ++ attr = tree_cons (get_identifier ("weak"), NULL_TREE, attr); ++ } ++ ++ decl_attributes (node, attr, flags); ++ ++ return NULL_TREE; ++} ++ + /* Handle an "visibility" attribute; arguments as in + struct attribute_spec.handler. */ + +--- gcc/defaults.h.orig 2005-11-15 19:54:00.000000000 -0200 ++++ gcc/defaults.h 2005-11-16 13:35:20.000000000 -0200 +@@ -182,6 +182,25 @@ + #endif + #endif + ++/* This is how we tell the assembler that a symbol is a weak alias to ++ another symbol that doesn't require the other symbol to be defined. ++ Uses of the former will turn into weak uses of the latter, i.e., ++ uses that, in case the latter is undefined, will not cause errors, ++ and will add it to the symbol table as weak undefined. However, if ++ the latter is referenced directly, a strong reference prevails. */ ++#ifndef ASM_OUTPUT_WEAKREF ++#define ASM_OUTPUT_WEAKREF(FILE, DECL, NAME, VALUE) \ ++ do \ ++ { \ ++ fprintf ((FILE), "\t.weakref\t"); \ ++ assemble_name ((FILE), (NAME)); \ ++ fprintf ((FILE), ","); \ ++ assemble_name ((FILE), (VALUE)); \ ++ fprintf ((FILE), "\n"); \ ++ } \ ++ while (0) ++#endif ++ + /* How to emit a .type directive. */ + #ifndef ASM_OUTPUT_TYPE_DIRECTIVE + #if defined TYPE_ASM_OP && defined TYPE_OPERAND_FMT +--- gcc/doc/extend.texi.orig 2005-11-15 19:54:00.000000000 -0200 ++++ gcc/doc/extend.texi 2005-11-15 19:54:02.000000000 -0200 +@@ -2356,6 +2356,38 @@ + for ELF targets, and also for a.out targets when using the GNU assembler + and linker. + ++@item weakref ++@itemx weakref ("@var{target}") ++@cindex @code{weakref} attribute ++The @code{weakref} attribute marks a declaration as a weak reference. ++Without arguments, it should be accompanied by an @code{alias} attribute ++naming the target symbol. Optionally, the @var{target} may be given as ++an argument to @code{weakref} itself. In either case, @code{weakref} ++implicitly marks the declaration as @code{weak}. Without a ++@var{target}, given as an argument to @code{weakref} or to @code{alias}, ++@code{weakref} is equivalent to @code{weak}. ++ ++@smallexample ++extern int x() __attribute__ ((weakref ("y"))); ++/* is equivalent to... */ ++extern int x() __attribute__ ((weak, weakref, alias ("y"))); ++/* and to... */ ++extern int x() __attribute__ ((weakref)); ++extern int x() __attribute__ ((alias ("y"))); ++@end smallexample ++ ++A weak reference is an alias that does not by itself require a ++definition to be given for the target symbol. If the target symbol is ++only referenced through weak references, then the becomes a @code{weak} ++undefined symbol. If it is directly referenced, however, then such ++strong references prevail, and a definition will be required for the ++symbol, not necessarily in the same translation unit. ++ ++The effect is equivalent to moving all references to the alias to a ++separate translation unit, renaming the alias to the aliased symbol, ++declaring it as weak, compiling the two separate translation units and ++performing a reloadable link on them. ++ + @item malloc + @cindex @code{malloc} attribute + The @code{malloc} attribute is used to tell the compiler that a function +--- gcc/gthr-posix.h.orig 2005-11-15 19:54:00.000000000 -0200 ++++ gcc/gthr-posix.h 2005-11-15 19:54:34.000000000 -0200 +@@ -58,8 +58,56 @@ + #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function + #endif + +-#if SUPPORTS_WEAK && GTHREAD_USE_WEAK ++#if SUPPORTS_WEAK && GTHREAD_USE_WEAK && defined __GNUC_RH_RELEASE__ \ ++ && ((__GNUC__ == 3 && __GNUC_MINOR__ == 4 && (__GNUC_PATCHLEVEL__ > 4 || (__GNUC_PATCHLEVEL__ == 4 && __GNUC_RH_RELEASE__ > 2))) \ ++ || (__GNUC__ == 4 && __GNUC_MINOR__ == 0 && (__GNUC_PATCHLEVEL__ > 2 || (__GNUC_PATCHLEVEL__ == 2 && __GNUC_RH_RELEASE__ > 6)))) \ ++ && ! defined __attribute__ ++# define __gthrw(name) \ ++ extern __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) ++ ++__gthrw(pthread_once); ++__gthrw(pthread_key_create); ++__gthrw(pthread_key_delete); ++__gthrw(pthread_getspecific); ++__gthrw(pthread_setspecific); ++__gthrw(pthread_create); ++ ++__gthrw(pthread_mutex_lock); ++__gthrw(pthread_mutex_trylock); ++__gthrw(pthread_mutex_unlock); ++__gthrw(pthread_mutexattr_init); ++__gthrw(pthread_mutexattr_settype); ++__gthrw(pthread_mutexattr_destroy); ++ ++__gthrw(pthread_mutex_init); + ++# if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) ++/* Objective-C. */ ++__gthrw(pthread_cond_broadcast); ++__gthrw(pthread_cond_destroy); ++__gthrw(pthread_cond_init); ++__gthrw(pthread_cond_signal); ++__gthrw(pthread_cond_wait); ++__gthrw(pthread_exit); ++__gthrw(pthread_mutex_destroy); ++__gthrw(pthread_self); ++/* These really should be protected by _POSIX_PRIORITY_SCHEDULING, but ++ we use them inside a _POSIX_THREAD_PRIORITY_SCHEDULING block. */ ++# ifdef _POSIX_THREAD_PRIORITY_SCHEDULING ++__gthrw(sched_get_priority_max); ++__gthrw(sched_get_priority_min); ++# endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ ++__gthrw(sched_yield); ++__gthrw(pthread_attr_destroy); ++__gthrw(pthread_attr_init); ++__gthrw(pthread_attr_setdetachstate); ++# ifdef _POSIX_THREAD_PRIORITY_SCHEDULING ++__gthrw(pthread_getschedparam); ++__gthrw(pthread_setschedparam); ++# endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ ++# endif /* _LIBOBJC || _LIBOBJC_WEAK */ ++#else ++# if SUPPORTS_WEAK && GTHREAD_USE_WEAK + #pragma weak pthread_once + #pragma weak pthread_key_create + #pragma weak pthread_key_delete +@@ -101,11 +146,58 @@ + #pragma weak pthread_setschedparam + #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ + #endif /* _LIBOBJC || _LIBOBJC_WEAK */ ++#endif /* SUPPORTS_WEAK && GTHREAD_USE_WEAK */ ++ ++#define __gthrw_pthread_once pthread_once ++#define __gthrw_pthread_key_create pthread_key_create ++#define __gthrw_pthread_key_delete pthread_key_delete ++#define __gthrw_pthread_getspecific pthread_getspecific ++#define __gthrw_pthread_setspecific pthread_setspecific ++#define __gthrw_pthread_create pthread_create ++ ++#define __gthrw_pthread_mutex_lock pthread_mutex_lock ++#define __gthrw_pthread_mutex_trylock pthread_mutex_trylock ++#define __gthrw_pthread_mutex_unlock pthread_mutex_unlock ++#define __gthrw_pthread_mutexattr_init pthread_mutexattr_init ++#define __gthrw_pthread_mutexattr_settype pthread_mutexattr_settype ++#define __gthrw_pthread_mutexattr_destroy pthread_mutexattr_destroy ++ ++#define __gthrw_pthread_mutex_init pthread_mutex_init ++ ++#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) ++/* Objective-C. */ ++#define __gthrw_pthread_cond_broadcast pthread_cond_broadcast ++#define __gthrw_pthread_cond_destroy pthread_cond_destroy ++#define __gthrw_pthread_cond_init pthread_cond_init ++#define __gthrw_pthread_cond_signal pthread_cond_signal ++#define __gthrw_pthread_cond_wait pthread_cond_wait ++#define __gthrw_pthread_exit pthread_exit ++#define __gthrw_pthread_mutex_destroy pthread_mutex_destroy ++#define __gthrw_pthread_self pthread_self ++/* These really should be protected by _POSIX_PRIORITY_SCHEDULING, but ++ we use them inside a _POSIX_THREAD_PRIORITY_SCHEDULING block. */ ++#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING ++#define __gthrw_sched_get_priority_max sched_get_priority_max ++#define __gthrw_sched_get_priority_min sched_get_priority_min ++#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ ++#define __gthrw_sched_yield sched_yield ++#define __gthrw_pthread_attr_destroy pthread_attr_destroy ++#define __gthrw_pthread_attr_init pthread_attr_init ++#define __gthrw_pthread_attr_setdetachstate pthread_attr_setdetachstate ++#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING ++#define __gthrw_pthread_getschedparam pthread_getschedparam ++#define __gthrw_pthread_setschedparam pthread_setschedparam ++#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ ++#endif /* _LIBOBJC || _LIBOBJC_WEAK */ ++#endif ++ ++ ++#if SUPPORTS_WEAK && GTHREAD_USE_WEAK + + static inline int + __gthread_active_p (void) + { +- static void *const __gthread_active_ptr = (void *) &pthread_create; ++ static void *const __gthread_active_ptr = (void *) &__gthrw_pthread_create; + return __gthread_active_ptr != 0; + } + +@@ -144,13 +236,13 @@ + if (__gthread_active_p ()) + { + /* Initialize the thread storage key */ +- if (pthread_key_create (&_objc_thread_storage, NULL) == 0) ++ if (__gthrw_pthread_key_create (&_objc_thread_storage, NULL) == 0) + { + /* The normal default detach state for threads is + * PTHREAD_CREATE_JOINABLE which causes threads to not die + * when you think they should. */ +- if (pthread_attr_init (&_objc_thread_attribs) == 0 +- && pthread_attr_setdetachstate (&_objc_thread_attribs, ++ if (__gthrw_pthread_attr_init (&_objc_thread_attribs) == 0 ++ && __gthrw_pthread_attr_setdetachstate (&_objc_thread_attribs, + PTHREAD_CREATE_DETACHED) == 0) + return 0; + } +@@ -164,8 +256,8 @@ + __gthread_objc_close_thread_system (void) + { + if (__gthread_active_p () +- && pthread_key_delete (_objc_thread_storage) == 0 +- && pthread_attr_destroy (&_objc_thread_attribs) == 0) ++ && __gthrw_pthread_key_delete (_objc_thread_storage) == 0 ++ && __gthrw_pthread_attr_destroy (&_objc_thread_attribs) == 0) + return 0; + + return -1; +@@ -183,7 +275,7 @@ + if (!__gthread_active_p ()) + return NULL; + +- if (!(pthread_create (&new_thread_handle, NULL, (void *) func, arg))) ++ if (!(__gthrw_pthread_create (&new_thread_handle, NULL, (void *) func, arg))) + thread_id = (objc_thread_t) new_thread_handle; + else + thread_id = NULL; +@@ -200,17 +292,17 @@ + else + { + #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING +- pthread_t thread_id = pthread_self (); ++ pthread_t thread_id = __gthrw_pthread_self (); + int policy; + struct sched_param params; + int priority_min, priority_max; + +- if (pthread_getschedparam (thread_id, &policy, ¶ms) == 0) ++ if (__gthrw_pthread_getschedparam (thread_id, &policy, ¶ms) == 0) + { +- if ((priority_max = sched_get_priority_max (policy)) == -1) ++ if ((priority_max = __gthrw_sched_get_priority_max (policy)) == -1) + return -1; + +- if ((priority_min = sched_get_priority_min (policy)) == -1) ++ if ((priority_min = __gthrw_sched_get_priority_min (policy)) == -1) + return -1; + + if (priority > priority_max) +@@ -224,7 +316,7 @@ + * this should be a pointer to policy but pthread.h is universally + * at odds with this. + */ +- if (pthread_setschedparam (thread_id, policy, ¶ms) == 0) ++ if (__gthrw_pthread_setschedparam (thread_id, policy, ¶ms) == 0) + return 0; + } + #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ +@@ -242,7 +334,7 @@ + int policy; + struct sched_param params; + +- if (pthread_getschedparam (pthread_self (), &policy, ¶ms) == 0) ++ if (__gthrw_pthread_getschedparam (__gthrw_pthread_self (), &policy, ¶ms) == 0) + return params.sched_priority; + else + return -1; +@@ -257,7 +349,7 @@ + __gthread_objc_thread_yield (void) + { + if (__gthread_active_p ()) +- sched_yield (); ++ __gthrw_sched_yield (); + } + + /* Terminate the current thread. */ +@@ -266,7 +358,7 @@ + { + if (__gthread_active_p ()) + /* exit the thread */ +- pthread_exit (&__objc_thread_exit_status); ++ __gthrw_pthread_exit (&__objc_thread_exit_status); + + /* Failed if we reached here */ + return -1; +@@ -277,7 +369,7 @@ + __gthread_objc_thread_id (void) + { + if (__gthread_active_p ()) +- return (objc_thread_t) pthread_self (); ++ return (objc_thread_t) __gthrw_pthread_self (); + else + return (objc_thread_t) 1; + } +@@ -287,7 +379,7 @@ + __gthread_objc_thread_set_data (void *value) + { + if (__gthread_active_p ()) +- return pthread_setspecific (_objc_thread_storage, value); ++ return __gthrw_pthread_setspecific (_objc_thread_storage, value); + else + { + thread_local_storage = value; +@@ -300,7 +392,7 @@ + __gthread_objc_thread_get_data (void) + { + if (__gthread_active_p ()) +- return pthread_getspecific (_objc_thread_storage); ++ return __gthrw_pthread_getspecific (_objc_thread_storage); + else + return thread_local_storage; + } +@@ -315,7 +407,7 @@ + { + mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); + +- if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend, NULL)) ++ if (__gthrw_pthread_mutex_init ((pthread_mutex_t *) mutex->backend, NULL)) + { + objc_free (mutex->backend); + mutex->backend = NULL; +@@ -336,18 +428,18 @@ + + /* + * Posix Threads specifically require that the thread be unlocked +- * for pthread_mutex_destroy to work. ++ * for __gthrw_pthread_mutex_destroy to work. + */ + + do + { +- count = pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend); ++ count = __gthrw_pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend); + if (count < 0) + return -1; + } + while (count); + +- if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend)) ++ if (__gthrw_pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend)) + return -1; + + objc_free (mutex->backend); +@@ -361,7 +453,7 @@ + __gthread_objc_mutex_lock (objc_mutex_t mutex) + { + if (__gthread_active_p () +- && pthread_mutex_lock ((pthread_mutex_t *) mutex->backend) != 0) ++ && __gthrw_pthread_mutex_lock ((pthread_mutex_t *) mutex->backend) != 0) + { + return -1; + } +@@ -374,7 +466,7 @@ + __gthread_objc_mutex_trylock (objc_mutex_t mutex) + { + if (__gthread_active_p () +- && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 0) ++ && __gthrw_pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 0) + { + return -1; + } +@@ -387,7 +479,7 @@ + __gthread_objc_mutex_unlock (objc_mutex_t mutex) + { + if (__gthread_active_p () +- && pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend) != 0) ++ && __gthrw_pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend) != 0) + { + return -1; + } +@@ -405,7 +497,7 @@ + { + condition->backend = objc_malloc (sizeof (pthread_cond_t)); + +- if (pthread_cond_init ((pthread_cond_t *) condition->backend, NULL)) ++ if (__gthrw_pthread_cond_init ((pthread_cond_t *) condition->backend, NULL)) + { + objc_free (condition->backend); + condition->backend = NULL; +@@ -422,7 +514,7 @@ + { + if (__gthread_active_p ()) + { +- if (pthread_cond_destroy ((pthread_cond_t *) condition->backend)) ++ if (__gthrw_pthread_cond_destroy ((pthread_cond_t *) condition->backend)) + return -1; + + objc_free (condition->backend); +@@ -436,7 +528,7 @@ + __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) + { + if (__gthread_active_p ()) +- return pthread_cond_wait ((pthread_cond_t *) condition->backend, ++ return __gthrw_pthread_cond_wait ((pthread_cond_t *) condition->backend, + (pthread_mutex_t *) mutex->backend); + else + return 0; +@@ -447,7 +539,7 @@ + __gthread_objc_condition_broadcast (objc_condition_t condition) + { + if (__gthread_active_p ()) +- return pthread_cond_broadcast ((pthread_cond_t *) condition->backend); ++ return __gthrw_pthread_cond_broadcast ((pthread_cond_t *) condition->backend); + else + return 0; + } +@@ -457,7 +549,7 @@ + __gthread_objc_condition_signal (objc_condition_t condition) + { + if (__gthread_active_p ()) +- return pthread_cond_signal ((pthread_cond_t *) condition->backend); ++ return __gthrw_pthread_cond_signal ((pthread_cond_t *) condition->backend); + else + return 0; + } +@@ -468,7 +560,7 @@ + __gthread_once (__gthread_once_t *once, void (*func) (void)) + { + if (__gthread_active_p ()) +- return pthread_once (once, func); ++ return __gthrw_pthread_once (once, func); + else + return -1; + } +@@ -476,32 +568,32 @@ + static inline int + __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) + { +- return pthread_key_create (key, dtor); ++ return __gthrw_pthread_key_create (key, dtor); + } + + static inline int + __gthread_key_delete (__gthread_key_t key) + { +- return pthread_key_delete (key); ++ return __gthrw_pthread_key_delete (key); + } + + static inline void * + __gthread_getspecific (__gthread_key_t key) + { +- return pthread_getspecific (key); ++ return __gthrw_pthread_getspecific (key); + } + + static inline int + __gthread_setspecific (__gthread_key_t key, const void *ptr) + { +- return pthread_setspecific (key, ptr); ++ return __gthrw_pthread_setspecific (key, ptr); + } + + static inline int + __gthread_mutex_lock (__gthread_mutex_t *mutex) + { + if (__gthread_active_p ()) +- return pthread_mutex_lock (mutex); ++ return __gthrw_pthread_mutex_lock (mutex); + else + return 0; + } +@@ -510,7 +602,7 @@ + __gthread_mutex_trylock (__gthread_mutex_t *mutex) + { + if (__gthread_active_p ()) +- return pthread_mutex_trylock (mutex); ++ return __gthrw_pthread_mutex_trylock (mutex); + else + return 0; + } +@@ -519,7 +611,7 @@ + __gthread_mutex_unlock (__gthread_mutex_t *mutex) + { + if (__gthread_active_p ()) +- return pthread_mutex_unlock (mutex); ++ return __gthrw_pthread_mutex_unlock (mutex); + else + return 0; + } +@@ -533,13 +625,13 @@ + pthread_mutexattr_t attr; + int r; + +- r = pthread_mutexattr_init (&attr); ++ r = __gthrw_pthread_mutexattr_init (&attr); + if (!r) +- r = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); ++ r = __gthrw_pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); + if (!r) +- r = pthread_mutex_init (mutex, &attr); ++ r = __gthrw_pthread_mutex_init (mutex, &attr); + if (!r) +- r = pthread_mutexattr_destroy (&attr); ++ r = __gthrw_pthread_mutexattr_destroy (&attr); + return r; + } + } +--- gcc/varasm.c.orig 2005-11-15 19:54:00.000000000 -0200 ++++ gcc/varasm.c 2005-11-16 13:32:07.000000000 -0200 +@@ -4393,6 +4393,9 @@ + if (! TREE_USED (decl)) + continue; + ++ if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) ++ continue; ++ + #ifdef ASM_WEAKEN_DECL + ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL); + #else +@@ -4506,6 +4509,18 @@ + we don't use it here. */ + make_decl_rtl (decl, NULL); + ++ if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) ++ { ++#ifdef ASM_OUTPUT_WEAKREF ++ ASM_OUTPUT_WEAKREF (asm_out_file, decl, ++ IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), ++ IDENTIFIER_POINTER (target)); ++#else ++ error ("%Jweakref is not supported in this configuration", decl); ++#endif ++ return; ++ } ++ + #ifdef ASM_OUTPUT_DEF + /* Make name accessible from other files, if appropriate. */ + +--- libobjc/thr-objc.c.orig 2005-11-15 19:54:00.000000000 -0200 ++++ libobjc/thr-objc.c 2005-11-15 19:54:02.000000000 -0200 +@@ -24,6 +24,10 @@ + covered by the GNU General Public License. */ + + #define _LIBOBJC ++/* The line below is needed for declarations of functions such as ++ pthread_mutexattr_settype, without which gthr-posix.h may fail to ++ compile within libobjc. */ ++#define _XOPEN_SOURCE 500 + #include "tconfig.h" + #include "coretypes.h" + #include "tm.h" +--- gcc/testsuite/g++.old-deja/g++.ext/weakref1.C 1970-01-01 00:00:00.000000000 +0000 ++++ gcc/testsuite/g++.old-deja/g++.ext/weakref1.C 2005-11-15 19:54:02.000000000 -0200 +@@ -0,0 +1,228 @@ ++// { dg-do run } ++// { dg-additional-sources " weakref1a.cc" } ++// { dg-require-weak "" } ++// { dg-options "-O2" } ++ ++// Copyright 2005 Free Software Foundation, Inc. ++// Contributed by Alexandre Oliva ++ ++// Torture test for weakrefs. The first letter of an identifier ++// indicates whether/how it is defined; the second letter indicates ++// whether it is part of a variable or function test; the number that ++// follows is a test counter, and a letter that may follow enables ++// multiple identifiers within the same test (e.g., multiple weakrefs ++// or pointers to the same identifier). ++ ++// Identifiers starting with W are weakrefs; those with p are ++// pointers; those with g are global definitions; those with l are ++// local definitions; those with w are expected to be weak undefined ++// in the symbol table; those with u are expected to be marked as ++// non-weak undefined in the symbol table. ++ ++#include ++ ++#define USED __attribute__((used)) ++ ++extern "C" { ++typedef int vtype; ++ ++extern vtype wv1; ++extern vtype Wv1a __attribute__((weakref ("wv1"))); ++static vtype *pv1a USED = &Wv1a; ++extern vtype Wv1b __attribute__((weak, weakref, alias ("wv1"))); ++static vtype *pv1b USED = &Wv1b; ++extern vtype Wv1c __attribute__((weakref)); ++extern vtype Wv1c __attribute__((alias ("wv1"))); ++static vtype *pv1c USED = &Wv1c; ++ ++vtype gv2; ++extern vtype Wv2a __attribute__((weakref ("gv2"))); ++static vtype *pv2a USED = &Wv2a; ++ ++static vtype lv3; ++extern vtype Wv3a __attribute__((weakref ("lv3"))); ++static vtype *pv3a USED = &Wv3a; ++ ++extern vtype uv4; ++extern vtype Wv4a __attribute__((weakref ("uv4"))); ++static vtype *pv4a USED = &Wv4a; ++static vtype *pv4 USED = &uv4; ++ ++extern vtype Wv5a __attribute__((weakref ("uv5"))); ++static vtype *pv5a USED = &Wv5a; ++extern vtype uv5; ++static vtype *pv5 USED = &uv5; ++ ++extern vtype Wv6a __attribute__((weakref ("wv6"))); ++static vtype *pv6a USED = &Wv6a; ++extern vtype wv6; ++ ++extern vtype Wv7a __attribute__((weakref ("uv7"))); ++static vtype* USED fv7 (void) { ++ return &Wv7a; ++} ++extern vtype uv7; ++static vtype* USED fv7a (void) { ++ return &uv7; ++} ++ ++extern vtype uv8; ++static vtype* USED fv8a (void) { ++ return &uv8; ++} ++extern vtype Wv8a __attribute__((weakref ("uv8"))); ++static vtype* USED fv8 (void) { ++ return &Wv8a; ++} ++ ++extern vtype wv9 __attribute__((weak)); ++extern vtype Wv9a __attribute__((weakref ("wv9"))); ++static vtype *pv9a USED = &Wv9a; ++ ++extern vtype Wv10a __attribute__((weakref ("Wv10b"))); ++extern vtype Wv10b __attribute__((weakref ("Wv10c"))); ++extern vtype Wv10c __attribute__((weakref ("Wv10d"))); ++extern vtype Wv10d __attribute__((weakref ("wv10"))); ++extern vtype wv10; ++ ++extern vtype wv11; ++extern vtype Wv11d __attribute__((weakref ("wv11"))); ++extern vtype Wv11c __attribute__((weakref ("Wv11d"))); ++extern vtype Wv11b __attribute__((weakref ("Wv11c"))); ++extern vtype Wv11a __attribute__((weakref ("Wv11b"))); ++ ++extern vtype Wv12 __attribute__((weakref ("wv12"))); ++extern vtype wv12 __attribute__((weak)); ++ ++extern vtype Wv13 __attribute__((weakref ("wv13"))); ++extern vtype wv13 __attribute__((weak)); ++ ++extern vtype Wv14a __attribute__((weakref ("wv14"))); ++extern vtype Wv14b __attribute__((weakref ("wv14"))); ++extern vtype wv14 __attribute__((weak)); ++ ++typedef void ftype(void); ++ ++extern ftype wf1; ++extern ftype Wf1a __attribute__((weakref ("wf1"))); ++static ftype *pf1a USED = &Wf1a; ++extern ftype Wf1b __attribute__((weak, weakref, alias ("wf1"))); ++static ftype *pf1b USED = &Wf1b; ++extern ftype Wf1c __attribute__((weakref)); ++extern ftype Wf1c __attribute__((alias ("wf1"))); ++static ftype *pf1c USED = &Wf1c; ++ ++void gf2(void) {} ++extern ftype Wf2a __attribute__((weakref ("gf2"))); ++static ftype *pf2a USED = &Wf2a; ++ ++static void lf3(void) {} ++extern ftype Wf3a __attribute__((weakref ("lf3"))); ++static ftype *pf3a USED = &Wf3a; ++ ++extern ftype uf4; ++extern ftype Wf4a __attribute__((weakref ("uf4"))); ++static ftype *pf4a USED = &Wf4a; ++static ftype *pf4 USED = &uf4; ++ ++extern ftype Wf5a __attribute__((weakref ("uf5"))); ++static ftype *pf5a USED = &Wf5a; ++extern ftype uf5; ++static ftype *pf5 USED = &uf5; ++ ++extern ftype Wf6a __attribute__((weakref ("wf6"))); ++static ftype *pf6a USED = &Wf6a; ++extern ftype wf6; ++ ++extern ftype Wf7a __attribute__((weakref ("uf7"))); ++static ftype* USED ff7 (void) { ++ return &Wf7a; ++} ++extern ftype uf7; ++static ftype* USED ff7a (void) { ++ return &uf7; ++} ++ ++extern ftype uf8; ++static ftype* USED ff8a (void) { ++ return &uf8; ++} ++extern ftype Wf8a __attribute__((weakref ("uf8"))); ++static ftype* USED ff8 (void) { ++ return &Wf8a; ++} ++ ++extern ftype wf9 __attribute__((weak)); ++extern ftype Wf9a __attribute__((weakref ("wf9"))); ++static ftype *pf9a USED = &Wf9a; ++ ++extern ftype Wf10a __attribute__((weakref ("Wf10b"))); ++extern ftype Wf10b __attribute__((weakref ("Wf10c"))); ++extern ftype Wf10c __attribute__((weakref ("Wf10d"))); ++extern ftype Wf10d __attribute__((weakref ("wf10"))); ++extern ftype wf10; ++ ++extern ftype wf11; ++extern ftype Wf11d __attribute__((weakref ("wf11"))); ++extern ftype Wf11c __attribute__((weakref ("Wf11d"))); ++extern ftype Wf11b __attribute__((weakref ("Wf11c"))); ++extern ftype Wf11a __attribute__((weakref ("Wf11b"))); ++ ++extern ftype Wf12 __attribute__((weakref ("wf12"))); ++extern ftype wf12 __attribute__((weak)); ++ ++extern ftype Wf13 __attribute__((weakref ("wf13"))); ++extern ftype wf13 __attribute__((weak)); ++ ++extern ftype Wf14a __attribute__((weakref ("wf14"))); ++extern ftype Wf14b __attribute__((weakref ("wf14"))); ++extern ftype wf14 __attribute__((weak)); ++} ++ ++#define chk(p) do { if (!p) abort (); } while (0) ++ ++int main () { ++ chk (!pv1a); ++ chk (!pv1b); ++ chk (!pv1c); ++ chk (pv2a); ++ chk (pv3a); ++ chk (pv4a); ++ chk (pv4); ++ chk (pv5a); ++ chk (pv5); ++ chk (!pv6a); ++ chk (fv7 ()); ++ chk (fv7a ()); ++ chk (fv8 ()); ++ chk (fv8a ()); ++ chk (!pv9a); ++ chk (!&Wv10a); ++ chk (!&Wv11a); ++ chk (!&Wv12); ++ chk (!&wv12); ++ chk (!&wv13); ++ chk (!&Wv14a); ++ ++ chk (!pf1a); ++ chk (!pf1b); ++ chk (!pf1c); ++ chk (pf2a); ++ chk (pf3a); ++ chk (pf4a); ++ chk (pf4); ++ chk (pf5a); ++ chk (pf5); ++ chk (!pf6a); ++ chk (ff7 ()); ++ chk (ff7a ()); ++ chk (ff8 ()); ++ chk (ff8a ()); ++ chk (!pf9a); ++ chk (!&Wf10a); ++ chk (!&Wf11a); ++ chk (!&Wf12); ++ chk (!&wf12); ++ chk (!&wf13); ++ chk (!&Wf14a); ++} +--- gcc/testsuite/g++.old-deja/g++.ext/weakref1a.cc 1970-01-01 00:00:00.000000000 +0000 ++++ gcc/testsuite/g++.old-deja/g++.ext/weakref1a.cc 2005-11-15 19:54:02.000000000 -0200 +@@ -0,0 +1,10 @@ ++extern "C" { ++int uv4; ++int uv5; ++int uv7; ++int uv8; ++void uf4 (void) {} ++void uf5 (void) {} ++void uf7 (void) {} ++void uf8 (void) {} ++} +--- gcc/config/rs6000/rs6000.h.orig 2005-11-16 13:29:07.000000000 -0200 ++++ gcc/config/rs6000/rs6000.h 2005-11-16 14:10:04.000000000 -0200 +@@ -2383,6 +2383,24 @@ + while (0) + #endif + ++#define ASM_OUTPUT_WEAKREF(FILE, DECL, NAME, VALUE) \ ++ do \ ++ { \ ++ fputs ("\t.weakref\t", (FILE)); \ ++ RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \ ++ fputs (", ", (FILE)); \ ++ RS6000_OUTPUT_BASENAME ((FILE), (VALUE)); \ ++ if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL \ ++ && DEFAULT_ABI == ABI_AIX && DOT_SYMBOLS) \ ++ { \ ++ fputs ("\n\t.weakref\t.", (FILE)); \ ++ RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \ ++ fputs (", .", (FILE)); \ ++ RS6000_OUTPUT_BASENAME ((FILE), (VALUE)); \ ++ } \ ++ fputc ('\n', (FILE)); \ ++ } while (0) ++ + /* This implements the `alias' attribute. */ + #undef ASM_OUTPUT_DEF_FROM_DECLS + #define ASM_OUTPUT_DEF_FROM_DECLS(FILE, DECL, TARGET) \ diff --git a/SPECS/compat-gcc-34.spec b/SPECS/compat-gcc-34.spec new file mode 100644 index 0000000..22e3a1e --- /dev/null +++ b/SPECS/compat-gcc-34.spec @@ -0,0 +1,458 @@ +%define DATE 20060404 +%define _unpackaged_files_terminate_build 0 +%define multilib_64_archs sparc64 ppc64 s390x x86_64 +%ifarch s390x +%define multilib_32_arch s390 +%endif +%ifarch sparc64 +%define multilib_32_arch sparc +%endif +%ifarch ppc64 +%define multilib_32_arch ppc +%endif +%ifarch x86_64 +%define multilib_32_arch i386 +%endif +Summary: Compatibility GNU Compiler Collection +Name: compat-gcc-34 +Version: 3.4.6 +Release: 32%{?dist} +# libgcc and crtstuff have an exception which allows +# linking it into any kind of programs or shared libraries without +# restrictions. +License: GPLv2+ and GPLv2+ with exceptions +Group: Development/Languages +Source0: gcc-%{version}-%{DATE}.tar.bz2 +Source1: dummylib.sh +URL: http://gcc.gnu.org +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) +# Need .eh_frame ld optimizations +# Need proper visibility support +# Need -pie support +# Need --as-needed/--no-as-needed support +# Need .weakref support +BuildRequires: binutils >= 2.16.91.0.5-1 +BuildRequires: zlib-devel, gettext, dejagnu, bison, flex, texinfo +# Make sure pthread.h doesn't contain __thread tokens +BuildRequires: glibc-devel >= 2.2.90-12 +# Need .eh_frame ld optimizations +# Need proper visibility support +# Need -pie support +# Need .weakref support +Requires: binutils >= 2.16.91.0.5-1 +# Make sure gdb will understand DW_FORM_strp +Conflicts: gdb < 5.1-2 +Requires: glibc-devel >= 2.2.90-12 +Requires: libgcc >= 4.1.0 +BuildRequires: elfutils-devel >= 0.72 +%ifarch %{multilib_64_archs} sparc sparcv9 ppc +# Ensure glibc{,-devel} is installed for both multilib arches +BuildRequires: /lib/libc.so.6 /usr/lib/libc.so /lib64/libc.so.6 /usr/lib64/libc.so +%endif +Provides: bundled(libiberty) + +Patch1: gcc34-multi32-hack.patch +Patch2: gcc34-ice-hack.patch +Patch3: gcc34-ppc64-m32-m64-multilib-only.patch +Patch4: gcc34-ia64-lib64.patch +Patch5: gcc34-java-nomulti.patch +Patch6: gcc34-gnuc-rh-release.patch +Patch7: gcc34-pr16104.patch +Patch8: gcc34-var-tracking-fix.patch +Patch9: gcc34-i386-movsi-insv.patch +Patch10: gcc34-pr18925.patch +Patch11: gcc34-pr14084.patch +Patch12: gcc34-hashtab-recursion.patch +Patch13: gcc34-java-jnilink.patch +Patch14: gcc34-pr21955.patch +Patch15: gcc34-vsb-stack.patch +Patch16: gcc34-pr18300.patch +Patch17: gcc34-rh156291.patch +Patch18: gcc34-weakref.patch +Patch19: gcc34-dwarf2-usefbreg.patch +Patch20: gcc34-dwarf2-prefer-1elt-vartracking.patch +Patch21: gcc34-dwarf2-pr20268.patch +Patch22: gcc34-dwarf2-inline-details.patch +Patch23: gcc34-dwarf2-frame_base.patch +Patch24: gcc34-dwarf2-i386-multreg1.patch +Patch25: gcc34-dwarf2-i386-multreg2.patch +Patch26: gcc34-rh176182.patch +Patch27: gcc34-pr11953.patch +Patch28: gcc34-pr23591.patch +Patch29: gcc34-pr26208.patch +Patch30: gcc34-pr8788.patch +Patch31: gcc34-rh137200.patch +Patch32: gcc34-rh172117.patch +Patch33: gcc34-rh172876.patch +Patch34: gcc34-rh178062.patch +Patch35: gcc34-pr21412.patch +Patch36: gcc34-sw2438.patch +Patch37: gcc34-pr26208-workaround.patch +Patch38: gcc34-libgcc_eh-hidden.patch +Patch39: gcc34-frame-base-loclist.patch +Patch40: gcc34-CVE-2006-3619.patch +Patch41: gcc34-dwarf2-inline-details-fix.patch +Patch42: gcc34-CXXABI131.patch +Patch43: gcc34-rh205919.patch +Patch44: gcc34-rh207277.patch +Patch45: gcc34-var-tracking-coalesce.patch +Patch46: gcc34-java-zoneinfo.patch +Patch47: gcc34-libgcc-additions.patch +Patch48: gcc34-pr24975.patch +Patch49: gcc34-rh233941.patch +Patch50: gcc34-rh234515.patch +Patch51: gcc34-rh235008.patch +Patch52: gcc34-rh235255.patch +Patch53: gcc34-rh242685.patch + +Patch100: gcc34-ldbl-hack.patch +Patch101: gcc34-makeinfo.patch +Patch102: gcc34-bison4.patch +Patch103: gcc34-pr56258.patch + +%define _gnu %{nil} +%ifarch sparc sparcv9 +%define gcc_target_platform sparc64-%{_vendor}-linux +%endif +%ifarch ppc +%define gcc_target_platform ppc64-%{_vendor}-linux +%endif +%ifnarch sparc sparcv9 ppc +%define gcc_target_platform %{_target_cpu}-%{_vendor}-linux +%endif + +%description +This package includes a GCC 3.4.6-RH compatibility compiler. + +%package -n compat-libf2c-34 +Summary: Fortran 77 compatibility runtime +Group: System Environment/Libraries +Autoreq: true +Obsoletes: libf2c, compat-libf2c-32 +Obsoletes: compat-gcc-34, compat-gcc-34-c++, compat-gcc-34-g77 + +%description -n compat-libf2c-34 +This package contains Fortran 77 shared library which is needed to run +Fortran 77 dynamically linked programs built by g77 3.4.x + +%prep +%setup -q -n gcc-%{version}-%{DATE} +%ifarch sparc sparcv9 ppc +%patch1 -p0 -b .multi32-hack~ +%endif +%patch2 -p0 -b .ice-hack~ +%patch3 -p0 -b .ppc64-m32-m64-multilib-only~ +%ifarch ia64 +%if "%{_lib}" == "lib64" +%patch4 -p0 -b .ia64-lib64~ +%endif +%endif +%patch5 -p0 -b .java-nomulti~ +%patch6 -p0 -b .gnuc-rh-release~ +%patch7 -p0 -b .pr16104~ +%patch8 -p0 -b .var-tracking-fix~ +%patch9 -p0 -b .i386-movsi-insv~ +%patch10 -p0 -b .pr18925~ +%patch11 -p0 -b .pr14084~ +%patch12 -p0 -b .hashtab-recursion~ +%patch13 -p0 -b .java-jnilink~ +%patch14 -p0 -b .pr21955~ +%patch15 -p0 -b .vsb-stack~ +%patch16 -p0 -b .pr18300~ +%patch17 -p0 -b .rh156291~ +%patch18 -p0 -b .weakref~ +%patch19 -p0 -b .dwarf2-usefbreg~ +%patch20 -p0 -b .dwarf2-prefer-1elt-vartracking~ +%patch21 -p0 -b .dwarf2-pr20268~ +%patch22 -p0 -b .dwarf2-inline-details~ +%patch23 -p0 -b .dwarf2-frame_base~ +%patch24 -p0 -b .dwarf2-i386-multreg1~ +%patch25 -p0 -b .dwarf2-i386-multreg2~ +%patch26 -p0 -b .rh176182~ +%patch27 -p0 -b .pr11953~ +%patch28 -p0 -b .pr23591~ +%patch29 -p0 -b .pr26208~ +%patch30 -p0 -b .pr8788~ +%patch31 -p0 -b .rh137200~ +%patch32 -p0 -b .rh172117~ +%patch33 -p0 -b .rh172876~ +%patch34 -p0 -b .rh178062~ +%patch35 -p0 -b .pr21412~ +%patch36 -p0 -b .sw2438~ +%patch37 -p0 -b .pr26208-workaround~ +%patch38 -p0 -b .libgcc_eh-hidden~ +%patch39 -p0 -b .frame-base-loclist~ +%patch40 -p0 -b .CVE-2006-3619~ +%patch41 -p0 -b .dwarf2-inline-details-fix~ +%patch42 -p0 -b .CXXABI131~ +%patch43 -p0 -b .rh205919~ +%patch44 -p0 -b .rh207277~ +%patch45 -p0 -b .var-tracking-coalesce~ +%patch46 -p0 -b .java-zoneinfo~ +%patch47 -p0 -b .libgcc-additions~ +%patch48 -p0 -b .pr24975~ +%patch49 -p0 -b .rh233941~ +%patch50 -p0 -b .rh234515~ +%patch51 -p0 -b .rh235008~ +%patch52 -p0 -b .rh235255~ +%patch53 -p0 -b .rh242685~ + +%patch100 -p0 -b .ldbl-hack~ +%patch101 -p0 -b .makeinfo~ +%patch102 -p0 -b .bison4 +%patch103 -p0 -b .pr56258~ + +sed -i -e 's/struct siginfo/siginfo_t/' gcc/config/*/linux*.h + +perl -pi -e 's/3\.4\.7/3.4.6/' gcc/version.c +perl -pi -e 's/"%{version}"/"%{version} \(release\)"/' gcc/version.c +perl -pi -e 's/\((prerelease|experimental|release|Red Hat[^)]*)\)/\(Red Hat %{version}-%{release}\)/' gcc/version.c + +./contrib/gcc_update --touch + +%build + +rm -fr obj-%{gcc_target_platform} +mkdir obj-%{gcc_target_platform} +cd obj-%{gcc_target_platform} + +mkdir -p ld_hack +cat > ld_hack/ld <<\EOF +#!/bin/sh +case " $* " in *\ -r\ *) exec /usr/bin/ld "$@";; esac +exec /usr/bin/ld --build-id "$@" +EOF +chmod 755 ld_hack/ld +export PATH=`pwd`/ld_hack/${PATH:+:$PATH} + +if [ ! -f /usr/lib/locale/de_DE/LC_CTYPE ]; then + mkdir locale + localedef -f ISO-8859-1 -i de_DE locale/de_DE + export LOCPATH=`pwd`/locale:/usr/lib/locale +fi + +CC=gcc +OPT_FLAGS=`echo $RPM_OPT_FLAGS|sed -e 's/-fno-rtti//g' -e 's/-fno-exceptions//g'` +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-m64//g;s/-m32//g;s/-m31//g'` +%ifarch %{ix86} +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-mtune=pentium4/-mtune=i686/g'` +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-mtune=generic/-mtune=i686/g'` +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-mtune=atom/-mtune=i686/g'` +%endif +%ifarch x86_64 +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-mtune=nocona//g'` +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-mtune=generic//g'` +%endif +%ifarch sparc sparcv9 sparc64 +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-mcpu=ultrasparc/-mtune=ultrasparc/g'` +%endif +%ifarch s390 s390x +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-march=z9-109//g;s/-march=z10//g;s/-march=z196//g;s/-mtune=z10//g;s/-mtune=zEC12//g'` +%endif +%ifarch ppc ppc64 +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-march=power[678]//g;s/-mcpu=power[678]//g;s/-mtune=power[678]//g'` +%endif +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-Wall//g' -e 's/-Wp,-D_FORTIFY_SOURCE=2//g'` +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-fexceptions//g' -e 's/-fasynchronous-unwind-tables//g'` +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-grecord-gcc-switches//g' -e 's/-fstack-protector-strong//g'` +OPT_FLAGS=`echo $OPT_FLAGS|sed -e 's/-fstack-protector//g' -e 's/--param=ssp-buffer-size=[0-9]*//g'` +%ifarch sparc64 +cat > gcc64 <<"EOF" +#!/bin/sh +exec /usr/bin/gcc -m64 "$@" +EOF +chmod +x gcc64 +CC=`pwd`/gcc64 +%endif +%ifarch ppc64 +if gcc -m64 -xc -S /dev/null -o - > /dev/null 2>&1; then + cat > gcc64 <<"EOF" +#!/bin/sh +exec /usr/bin/gcc -m64 "$@" +EOF + chmod +x gcc64 + CC=`pwd`/gcc64 +fi +%endif +CC="$CC" CFLAGS="$OPT_FLAGS" CXXFLAGS="$OPT_FLAGS" XCFLAGS="$OPT_FLAGS" TCFLAGS="$OPT_FLAGS" \ + GCJFLAGS="$OPT_FLAGS" \ + ../configure --prefix=%{_prefix} --mandir=%{_mandir} --infodir=%{_infodir} \ + --enable-shared --enable-threads=posix --disable-checking \ + --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions \ + --enable-languages=c,f77 --disable-libgcj \ +%ifarch sparc sparcv9 + --host=%{gcc_target_platform} --build=%{gcc_target_platform} --target=%{gcc_target_platform} --with-cpu=v7 +%endif +%ifarch ppc + --host=%{gcc_target_platform} --build=%{gcc_target_platform} --target=%{gcc_target_platform} --with-cpu=default32 +%endif +%ifnarch sparc sparcv9 ppc + --host=%{gcc_target_platform} +%endif + +make %{?_smp_mflags} BOOT_CFLAGS="$OPT_FLAGS" bootstrap-lean + +# Make sure we are using system libgcc_s, as system libstdc++.so.6 might +# use unwinding features that require it. +mv gcc/libgcc_s.so.1{,.bak} +ln -sf /%{_lib}/libgcc_s.so.1 gcc/libgcc_s.so.1 + +# run the tests. +make %{?_smp_mflags} -k check || : +echo ====================TESTING========================= +( ../contrib/test_summary || : ) 2>&1 | sed -n '/^cat.*EOF/,/^EOF/{/^cat.*EOF/d;/^EOF/d;/^LAST_UPDATED:/d;p;}' +echo ====================TESTING END===================== + +%install +rm -fr $RPM_BUILD_ROOT + +export PATH=`pwd`/obj-%{gcc_target_platform}/ld_hack/${PATH:+:$PATH} + +cd obj-%{gcc_target_platform} + +if [ ! -f /usr/lib/locale/de_DE/LC_CTYPE ]; then + export LOCPATH=`pwd`/locale:/usr/lib/locale +fi + +TARGET_PLATFORM=%{gcc_target_platform} +FULLPATH=$RPM_BUILD_ROOT%{_prefix}/lib/gcc/%{gcc_target_platform}/%{version} +mkdir -p $FULLPATH/include + +make prefix=$RPM_BUILD_ROOT%{_prefix} mandir=$RPM_BUILD_ROOT%{_mandir} \ + infodir=$RPM_BUILD_ROOT%{_infodir} install-target-libf2c + +rm -f $RPM_BUILD_ROOT%{_prefix}/%{_lib}/lib*.*a +chmod 755 $RPM_BUILD_ROOT%{_prefix}/%{_lib}/libg2c.so.0.* + +%ifarch %{multilib_64_archs} +# Remove libraries for the other arch on multilib arches +rm -f $RPM_BUILD_ROOT%{_prefix}/lib/lib*.so* +rm -f $RPM_BUILD_ROOT%{_prefix}/lib/lib*.a +%else +%ifarch sparc sparcv9 ppc +rm -f $RPM_BUILD_ROOT%{_prefix}/lib64/lib*.so* +rm -f $RPM_BUILD_ROOT%{_prefix}/lib64/lib*.a +%endif +%endif + +%clean +rm -rf $RPM_BUILD_ROOT + +%post -n compat-libf2c-34 -p /sbin/ldconfig + +%postun -n compat-libf2c-34 -p /sbin/ldconfig + +%files -n compat-libf2c-34 +%defattr(-,root,root) +%{_prefix}/%{_lib}/libg2c.so.0* +%doc gcc/f/ChangeLog* gcc/COPYING* + +%changelog +* Fri Jan 24 2014 Daniel Mach - 3.4.6-32 +- Mass rebuild 2014-01-24 + +* Tue Jan 7 2014 Jakub Jelinek 3.4.6-31 +- filter out -fstack-protector-strong (#1048851) + +* Fri Dec 27 2013 Daniel Mach - 3.4.6-31 +- Mass rebuild 2013-12-27 + +* Fri Jul 19 2013 Jakub Jelinek 3.4.6-30 +- only include compat-libf2c-34 subpackages and nothing else + +* Wed Feb 20 2013 Jakub Jelinek 3.4.6-29 +- don't conflict with libstdc++ 4.8.x, it is still backwards ABI compatible + +* Wed Feb 20 2013 Jakub Jelinek 3.4.6-28 +- use siginfo_t instead of struct siginfo +- fix build with makeinfo >= 5.0 (PR bootstrap/56258) + +* Wed Feb 13 2013 Fedora Release Engineering - 3.4.6-27 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Mon Oct 15 2012 Jon Ciesla - 3.4.6-26 +- Provides: bundled(libiberty) + +* Wed Jul 18 2012 Fedora Release Engineering - 3.4.6-25 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Wed Feb 1 2012 Jakub Jelinek 3.4.6-24 +- don't conflict with libstdc++ 4.7.x, it is still backwards ABI compatible + +* Thu Jan 12 2012 Fedora Release Engineering - 3.4.6-23 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Feb 08 2011 Fedora Release Engineering - 3.4.6-22 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Fri Jan 28 2011 Jakub Jelinek 3.4.6-21 +- don't conflict with libstdc++ 4.6.x, it is still backwards ABI compatible + +* Thu Jul 8 2010 Jakub Jelinek 3.4.6-20 +- don't conflict with libstdc++ 4.5.x, it is still backwards ABI compatible + +* Mon Jun 28 2010 Jakub Jelinek 3.4.6-19 +- add %%{?dist} (#604538) + +* Mon Nov 30 2009 Dennis Gregorovic - 3.4.6-18.1 +- Rebuilt for RHEL 6 + +* Mon Aug 31 2009 Karsten Hopp 3.4.6-18 +- strip -march=z9-109 and -mtune=z10 from OPT_FLAGS on s390, s390x + (#519507) + +* Fri Jul 31 2009 Jakub Jelinek 3.4.6-17 +- make sure to use system libgcc_s.so.1 instead of gcc34 one during + testing + +* Tue Jul 28 2009 Jakub Jelinek 3.4.6-16 +- replace -mtune=atom in $RPM_OPT_FLAGS with something that + GCC 3.4.6 groks + +* Fri Jul 24 2009 Fedora Release Engineering 3.4.6-15 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Fri Jun 12 2009 Dennis Gilmore - 3.4.6-14 +- setup to build sparcv9 + +* Tue Feb 24 2009 Fedora Release Engineering - 3.4.6-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Sun Feb 10 2008 Jakub Jelinek 3.4.6-12 +- rebuild with gcc 4.4, allow libstdc++ 4.1.0 ... 4.4.x + +* Fri Feb 1 2008 Jakub Jelinek 3.4.6-9 +- rebuild with gcc 4.3, allow libstdc++ 4.1.0 ... 4.3.x + +* Tue Oct 16 2007 Jakub Jelinek 3.4.6-8 +- update License tag +- build with ld --build-id +- grok makeinfo >= 4.10 during configury +- avoid aliasing warnings in libstdc++-v3 headers when compiled + with g++ 4.x (Paolo Carlini, PR libstdc++/24975, #240020) +- fix RTL expansion of COMPLEX_EXPR (#233941) +- fix deque<>::erase(iterator, iterator) (Steve LoBasso, + Paolo Carlini, #234515) +- fix french and kinyarwanda translations (#235008) +- handle PARALLELs in GCSE store motion (Alexandre Oliva, #235255) +- ensure zero termination for invalid, overly long, std::__enc_traits + internal or external character set names (Jatin Nansi, #242685) + +* Sat Mar 3 2007 Jakub Jelinek 3.4.6-7 +- ignore install-info failures in scriptlets (#223680) +- don't include cpp.debug in compat-gcc-34-debuginfo (#227021) +- fix .debug_line for inline function parameter blocks + (Alexandre Oliva, #214353) +- fix hang in vt_find_locations with -O{2,3} -g + (Alexandre Oliva, #216695, #218377) +- fix if-conversion ICE (Eric Botcazou, #207277) +- fix template instantiation ICE (Alexandre Oliva, #205919) + +* Wed Aug 23 2006 Jakub Jelinek 3.4.6-4 +- buildrequire elfutils-devel, so that libgcc_s is properly built + on ia64 +- on ppc*/s390* make sure all needed math *l stubs are included +- add -lnldbl_nonshared to ppc*/s390* specs + +* Wed Aug 9 2006 Jakub Jelinek 3.4.6-3 +- new compat package