This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug rtl-optimization/36419] [4.3 Regression] Wrong unwind info with -Os -fasynchronous-unwind-tables
- From: "jakub at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 2 Jun 2008 20:15:49 -0000
- Subject: [Bug rtl-optimization/36419] [4.3 Regression] Wrong unwind info with -Os -fasynchronous-unwind-tables
- References: <bug-36419-87@http.gcc.gnu.org/bugzilla/>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- 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