aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/opt/const1.C
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/testsuite/g++.dg/opt/const1.C')
-rw-r--r--gcc/testsuite/g++.dg/opt/const1.C129
1 files changed, 129 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/opt/const1.C b/gcc/testsuite/g++.dg/opt/const1.C
new file mode 100644
index 00000000000..834cfd5e258
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/const1.C
@@ -0,0 +1,129 @@
+// This testcase was miscompiled on IA-64 to read from unitialized memory
+// and dereference it.
+// { dg-do run }
+// { dg-options "-O2" }
+
+struct A
+{
+ A () { a = 1; }
+ void a1 () { a++; }
+ bool a2 () { return !--a; }
+ unsigned int a;
+};
+
+struct B {};
+
+template <class T> struct C
+{
+ C () {}
+ C (const T& t) : c (t) {}
+ C<T> *next, *prev;
+ T c;
+};
+
+template <class T> struct D
+{
+ C<T> *d;
+ D () : d (0) {}
+ D (C<T> *x) : d (x) {}
+ D (const D<T>& x) : d (x.d) {}
+ bool operator!= (const D<T>& x) const { return d != x.d; }
+ const T& operator* () const { return d->c; }
+ D<T> operator++ (int) { D<T> t = *this; d = d->next; return t; }
+};
+
+template <class T> struct E
+{
+ C<T> *e;
+ E () : e (0) {}
+ E (C<T> *p) : e (p) {}
+ E (const E<T>& x) : e (x.e) {}
+ E (const D<T>& x) : e (x.e) {}
+ bool operator!= (const E<T>& x) const { return e != x.e; }
+ const T& operator* () const { return e->c; }
+ E<T>& operator++ () { e = e->next; return *this; }
+};
+
+template <class T> struct F : public A
+{
+ C<T> *f;
+ unsigned long f0;
+ F () { f = new C<T>; f->next = f->prev = f; f0 = 0; }
+ F (const F<T>& x) : A ()
+ {
+ f = new C<T>; f->next = f->prev = f; f0 = 0;
+ D<T> b (x.f->next), e (x.f), i (f);
+ while (b != e)
+ f1 (i, *b++);
+ }
+
+ ~F ()
+ {
+ C<T> *p = f->next;
+ while (p != f)
+ {
+ C<T> *x = p->next;
+ delete p;
+ p = x;
+ }
+ delete f;
+ }
+
+ D<T> f1 (D<T> x, const T& y)
+ {
+ C<T> *p = new C<T> (y);
+ p->next = x.d;
+ p->prev = x.d->prev;
+ x.d->prev->next = p;
+ x.d->prev = p;
+ f0++;
+ return p;
+ }
+};
+
+template <class T> struct G
+{
+ F<T> *g;
+ G () { g = new F<T>; }
+ G (const G<T>& x) { g = x.g; g->a1 (); }
+ ~G () {}
+ G<T>& operator= (const G<T>& x) { x.g->a1 (); g = x.g; return *this; }
+ D<T> g1 () { g4 (); return D<T> (g->f); }
+ E<T> g1 () const { return E<T> (g->f); }
+ E<T> g2 () const { return E<T> (g->f->next); }
+ D<T> g3 (const T& x) { g4 (); return g->f1 (g1 (), x); }
+ void g4 () { if (g->a > 1) { g->a2 (); g = new F<T> (*g); } }
+
+ G<T> operator+ (const G<T>& x) const
+ {
+ G<T> x2 (*this);
+ for (E<T> i = x.g2 (); i != x.g1 (); ++i)
+ x2.g3 (*i);
+ return x2;
+ }
+
+ G<T>& operator+= (const G<T>& x)
+ {
+ for (E<T> i = x.g2 (); i != x.g1 (); ++i)
+ g3 (*i);
+ return *this;
+ }
+};
+
+struct H : public G<B>
+{
+ H () {}
+ H (const H& x) : G<B> (x) {}
+ H (const G<B>& x) : G<B> (x) {}
+};
+
+void foo ();
+
+int
+main ()
+{
+ H a = H () + H ();
+ a += H ();
+ H b;
+ b = H () + H ();
+}