------- Comment #4 from jakub at gcc dot gnu dot org  2008-06-02 20:15 -------
Here is a testcase that can be run, unfortunately during the simplification the
incorrect behavior changed from the stack pointer increasing in each iteration
by 16 bytes into decreasing in each iteration by 4 bytes.  That's wrong too of
course.

// { dg-options "-Os -fasynchronous-unwind-tables -fpic -fno-inline" }

extern "C"
{
  struct FILE;
  extern FILE *stderr;
  extern int fprintf (FILE *, const char *, ...);

  struct R { int r1; unsigned short r2[1]; };
  int bar1 (unsigned short *, int, short) throw ();
  void bar2 (R *) throw ();
  void bar3 (R **, const unsigned short *, int) throw ();
  void bar4 (R **, const char *) throw ();
}
struct S
{
  R *s;
  struct T { };
  S (R *x, T *) { s = x; }
  ~S () { bar2 (s); }
  S &operator= (const S &x);
  S &operator+= (const S &x);
  S sfn1 (const S &x) const;
  friend S operator+ (const S &x1, const S &x2);
  static S sfn2 (int i)
  {
    unsigned short q[33];
    R *p = 0;
    bar3 (&p, q, bar1 (q, i, 10));
    return S (p, (T *) 0);
  }
  static S sfn3 (const char *x)
  {
    R *p = 0;
    bar4 (&p, x);
    return S (p, (T *) 0);
  }
};

struct U { };
template <class C> unsigned char operator >>= (const U &, C &);

struct V;
struct W
{
  V *w;
  unsigned char is () const;
};

template <class T> struct X : public W
{
  inline ~X ();
  X ();
  X (const W &);
  T *operator -> () const;
};

struct E
{
  E ();
  E (const S &, const X <V> &);
  E (E const &);
  ~E ();
  E &operator = (E const &);
};

struct V
{
  virtual void release () throw ();
};

template <class T> X <T>::~X ()
{
  if (w)
    w->release ();
}

struct Y
{
  virtual U yfn1 (const S &);
};

struct Z;

X <V> baz1 (const S &) throw (E);
X <Z> baz2 (const X <Z> &) throw (E);

template <typename T> X<T>::X ()
{
  w = __null;
}

template <typename T> X<T>::X (W const &)
{
  w = __null;
}

U Y::yfn1 (const S &)
{
  throw 12;
}

Y y;

template <typename T> T *X<T>::operator -> () const
{
  return &y;
}

X <V> baz1 (const S &) throw (E)
{
  return X<V> ();
}

E::E ()
{
}

E::~E ()
{
}

X <Z> baz2 (const X <Z> &) throw (E)
{
  throw E ();
}

int bar1 (unsigned short *, int, short) throw ()
{
  asm volatile ("" : : : "memory");
  return 0;
}

void bar2 (R *) throw ()
{
  asm volatile ("" : : : "memory");
}

void bar3 (R **, const unsigned short *, int) throw ()
{
  asm volatile ("" : : : "memory");
}

void bar4 (R **, const char *) throw ()
{
  asm volatile ("" : : : "memory");
}

unsigned char W::is () const
{
  return 1;
}

S &S::operator += (const S &)
{
  return *this;
}

template <class C> unsigned char operator >>= (const U &, C &)
{
  throw 1;
}

template X<Y>::X ();
template X<Z>::X ();
template unsigned char operator >>= (const U &, X<Z> &);
template X<Y>::X (W const &);

template Y *X<Y>::operator-> () const;

X <Z> foo () throw ()
{
  X <Z> a;
  X <Y> b;
  try
  {
    b = X <Y> (baz1 (S::sfn3 ("defg")));
  }
  catch (E &)
  {
  }
  if (b.is ())
    {
      for (int n = 0; n < 10; n++)
        {
          S c = S::sfn3 ("abcd");
          c += S::sfn2 (n);
          X <Z> d;
          try
          {
            fprintf (stderr, "trying %d\n", n);
            if ((b->yfn1 (c) >>= d))
              if (d.is ())
                {
                  fprintf (stderr, "failure1 on %d\n", n);
                  a = baz2 (d);
                  if (a.is ())
                    break;
                }
              fprintf (stderr, "failure2 on %d\n", n);
          }
          catch (...)
          {
            void *p;
            asm volatile ("movl %%esp, %0" : "=r" (p));
            fprintf (stderr, "caught %d %p\n", n, p);
          }
        }
    }
  return a;
}

int
main ()
{
  foo ();
  return 0;
}


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36419

Reply via email to