]> git.pld-linux.org Git - packages/compat-gcc-34.git/commitdiff
- bunch of upstream/rh fixes (taken from rh)
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Mon, 4 Aug 2008 22:59:22 +0000 (22:59 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    compat-gcc-34-cxxabi.patch -> 1.1
    compat-gcc-34-pr-rh.patch -> 1.1

compat-gcc-34-cxxabi.patch [new file with mode: 0644]
compat-gcc-34-pr-rh.patch [new file with mode: 0644]

diff --git a/compat-gcc-34-cxxabi.patch b/compat-gcc-34-cxxabi.patch
new file mode 100644 (file)
index 0000000..1797a85
--- /dev/null
@@ -0,0 +1,47 @@
+2005-02-18  Richard Henderson  <rth@redhat.com>
+
+       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 *
+ __cxxabiv1::__cxa_begin_catch (void *exc_obj_in) throw()
diff --git a/compat-gcc-34-pr-rh.patch b/compat-gcc-34-pr-rh.patch
new file mode 100644 (file)
index 0000000..4b8dd87
--- /dev/null
@@ -0,0 +1,3127 @@
+2006-02-17  Jakub Jelinek  <jakub@redhat.com>
+
+       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 <pthread.h> 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
+2004-05-27  Josef Zlomek  <zlomekj@suse.cz>
+
+       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;
+2005-01-13  Jakub Jelinek  <jakub@redhat.com>
+
+       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;
++}
+2005-09-07  Jakub Jelinek  <jakub@redhat.com>
+
+       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  <zak@transversal.com>
+
+       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 <zak@transversal.com>
++
++struct base1 { };
++struct base2 { };
++struct base3 { };
++
++struct derived : base1, base2, base3 { };
++
++void foo(derived);
++
++int main()
++{
++  foo(derived());
++}
++
+2004-12-13  Mark Mitchell  <mark@codesourcery.com>
+
+       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--; 
++} 
+2005-05-07  Richard Henderson  <rth@redhat.com>
+
+       PR target/21412
+       * config/rs6000/rs6000.c (rs6000_emit_move): Look for tls addresses
+       with constant offsets.
+
+2004-07-11  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390.c (legitimize_tls_address): Handle constant offsets
+       added to TLS symbol addresses.
+
+2004-07-06  Richard Henderson  <rth@redhat.com>
+
+       * 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  <jakub@redhat.com>
+
+       * 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;
++}
+2005-07-22  Jakub Jelinek  <jakub@redhat.com>
+
+       * 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  <bkoz@redhat.com>
+
+       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<wchar_t>; 
+ #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 <sstream>
++
++namespace std
++{
++  // These symbols are hidden in libstdc++.so, as it is undesirable to export
++  // @@GLIBCXX_3.4.6
++  template streamsize basic_stringbuf<char, char_traits<char>, allocator<char> >::showmanyc();
++  template streamsize basic_stringbuf<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >::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<char_type*>(_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<std::streamsize>(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<std::streamoff>(str_01.length()) );
+   VERIFY( strmof_2 == static_cast<std::streamoff>(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 <sstream>
++#include <testsuite_hooks.h>
++#include <stdexcept>
++
++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  <bkoz@redhat.com>
++
++// 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 <fstream>
++#include <testsuite_hooks.h>
++
++typedef std::basic_streambuf<char>    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  <bkoz@redhat.com>
++
++// 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 <fstream>
++#include <testsuite_hooks.h>
++
++typedef std::basic_streambuf<wchar_t>         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/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
+2005-11-23  Paolo Carlini  <pcarlini@suse.de>
+
+       PR libstdc++/24975 (basic_string)
+       * include/bits/basic_string.h (_Rep::_S_empty_rep): Avoid
+       strict-aliasing warnings.
+
+2005-11-22  Paolo Carlini  <pcarlini@suse.de>
+
+       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<void*>(&_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<typename _InputIterator>
+       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 _Key, typename _Val, typename _KeyOfValue,
++           typename _Compare, typename _Alloc>
++    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 _Key, typename _Val, typename _KeyOfValue,
+            typename _Compare, typename _Alloc>
+     typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator
+@@ -928,6 +976,54 @@ namespace std
+       }
+     }
++#if __GNUC__ >= 4
++  template<typename _Key, typename _Val, typename _KeyOfValue,
++           typename _Compare, typename _Alloc>
++    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 _Key, typename _Val, typename _KeyOfValue,
+            typename _Compare, typename _Alloc>
+     typename _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::iterator
+@@ -974,6 +1070,54 @@ namespace std
+       }
+     }
++#if __GNUC__ >= 4
++  template<typename _Key, typename _Val, typename _KeyOfValue,
++           typename _Compare, typename _Alloc>
++    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<typename _Key, typename _Val, typename _KoV,
+            typename _Cmp, typename _Alloc>
+     template<class _II>
+@@ -1008,6 +1152,20 @@ namespace std
+       --_M_impl._M_node_count;
+     }
++#if __GNUC__ >= 4
++  template<typename _Key, typename _Val, typename _KeyOfValue,
++           typename _Compare, typename _Alloc>
++    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 _Key, typename _Val, typename _KeyOfValue,
+            typename _Compare, typename _Alloc>
+     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<typename _Key, typename _Val, typename _KeyOfValue,
++           typename _Compare, typename _Alloc>
++    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<typename _Key, typename _Val, typename _KeyOfValue,
+            typename _Compare, typename _Alloc>
+     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
+       }
+       /**
+2006-02-27  Jakub Jelinek  <jakub@redhat.com>
+
+       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/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)&regs_->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;
\f
+@@ -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);
+ }
+--- 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 <endian.h>
+ #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 <dlfcn.h>
++
++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;
+2005-05-08  Roger Sayle  <roger@eyesopen.com>
+
+       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)
+@@ -877,7 +877,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 (0, "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)
++    );
++}
++
+2005-11-30  Alexandre Oliva  <aoliva@redhat.com>
+
+       * gcc.c (find_a_file): Use update_path before access tests.
+       Mostly from Thomas Walker <thomas.walker@morganstanley.com>
+       * 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.  */
+2005-09-29  Alexandre Oliva  <aoliva@redhat.com>
+
+       * error.c (dump_type) <UNKNOWN_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, "<unknown type>");
++      pp_identifier (cxx_pp, "<unresolved overloaded function type>");
+       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 <typename T> void bar(T f);
++
++void baz() {
++  bar(foo); // { dg-error "<unresolved overloaded function type>" }
++}
+2005-12-18  Alexandre Oliva  <aoliva@redhat.com>
+
+       * 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  <jakub@redhat.com>
+
+       * 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;
++}
+2006-03-01  Alexandre Oliva  <aoliva@redhat.com>
+
+       * 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);
+2006-02-25  Alexandre Oliva  <aoliva@redhat.com>
+
+       * 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 <altivec.h>
++
++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 };
+2006-12-08  Alexandre Oliva  <aoliva@redhat.com>
+
+       * g++.dg/template/array17.C: New test.
+
+2006-10-27  Alexandre Oliva  <aoliva@redhat.com>
+
+       * 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 <typename T>
++struct V {
++  T& operator[](int);
++};
++
++struct S {
++  S operator +(int);
++  template <typename T> T value();
++};
++
++template <typename T>
++void R (T v)
++{
++  v[(S() + 0).template value<int>()][0] = 0;
++}
++
++int
++main ()
++{
++  R(V<V<int> >());
++}
+2006-12-08  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/opt/ifcvt1.C: New test.
+
+2005-11-09  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * 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;
++}
+2007-04-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * expr.c (expand_expr_real) <case COMPLEX_EXPR>: 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
+2007-01-24   Steve LoBasso <slobasso@yahoo.com>
+            Paolo Carlini  <pcarlini@suse.de>
+
+       * 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<size_type>(__elems_before) < (size() - __n) / 2)
++        if (static_cast<size_type>(__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 <deque>
++#include <testsuite_hooks.h>
++
++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<copy_tracker> 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;
++}
+2007-04-12  Jakub Jelinek  <jakub@redhat.com>
+
+       * 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'"
+2007-04-21  Alexandre Oliva  <aoliva@redhat.com>
+
+       * 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;
++}
+2007-06-08  Jatin Nansi  <jnansi@redhat.com>
+
+       * 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();
This page took 0.401369 seconds and 4 git commands to generate.