text: /* This testcase is part of GDB, the GNU debugger.
  
     Copyright 2008-2016 Free Software Foundation, Inc.
  
     Contributed by Red Hat, originally written by Keith Seitz.
  
     This program 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 3 of the License, or
     (at your option) any later version.
  
     This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
  
     Please email any bugs, comments, and/or additions to this file to:
     bug-gdb@gnu.org  */
  
  #include <stdlib.h>
  #include <iostream>
  
  // Forward decls
  class base;
  class derived;
  
  // A simple template with specializations
  template <typename T>
  class tclass
  {
  public:
    void do_something () { } // tclass<T>::do_something
  };
  
  template <>
  void tclass<char>::do_something () { } // tclass<char>::do_something
  
  template <>
  void tclass<int>::do_something () { } // tclass<int>::do_something
  
  template<>
  void tclass<long>::do_something () { } // tclass<long>::do_something
  
  template<>
  void tclass<short>::do_something () { } // tclass<short>::do_something
  
  // A simple template with multiple template parameters
  template <class A, class B, class C, class D, class E>
  void flubber (void) { // flubber
    A a;
    B b;
    C c;
    D d;
    E e;
  
    ++a;
    ++b;
    ++c;
    ++d;
    ++e;
  }
  
  // Some contrived policies
  template <class T>
  struct operation_1
  {
    static void function (void) { } // operation_1<T>::function
  };
  
  template <class T>
  struct operation_2
  {
    static void function (void) { } // operation_2<T>::function
  };
  
  template <class T>
  struct operation_3
  {
    static void function (void) { } // operation_3<T>::function
  };
  
  template <class T>
  struct operation_4
  {
    static void function (void) { } // operation_4<T>::function
  };
  
  // A policy-based class w/ and w/o default policy
  template <class T, class Policy>
  class policy : public Policy
  {
  public:
    policy (T obj) : obj_ (obj) { } // policy<T, Policy>::policy
  
  private:
    T obj_;
  };
  
  template <class T, class Policy = operation_1<T> >
  class policyd : public Policy
  {
  public:
    policyd (T obj) : obj_ (obj) { } // policyd<T, Policy>::policyd
    ~policyd (void) { } // policyd<T, Policy>::~policyd
  
  private:
    T obj_;
  };
  
  typedef policy<int, operation_1<void*> > policy1;
  typedef policy<int, operation_2<void*> > policy2;
  typedef policy<int, operation_3<void*> > policy3;
  typedef policy<int, operation_4<void*> > policy4;
  
  typedef policyd<int> policyd1;
  typedef policyd<long> policyd2;
  typedef policyd<char> policyd3;
  typedef policyd<base> policyd4;
  typedef policyd<tclass<int> > policyd5;
  
  class fluff { };
  static fluff *g_fluff = new fluff ();
  
  class base
  {
  protected:
    int foo_;
  
  public:
    base (void) : foo_ (42) { } // base::base(void)
    base (int foo) : foo_ (foo) { } // base::base(int)
    ~base (void) { } // base::~base
  
    // Some overloaded methods
    int overload (void) const { return 0; } // base::overload(void) const
    int overload (int i) const { return 1; } // base::overload(int) const
    int overload (short s) const { return 2; } // base::overload(short) const
    int overload (long l) const { return 3; } // base::overload(long) const
    int overload (char* a) const { return 4; } // base::overload(char*) const
    int overload (base& b) const { return 5; } // base::overload(base&) const
  
    // Operators
    int operator+ (base const& o) const { // base::operator+
      return foo_ + o.foo_;  }
  
    base operator++ (void) { // base::operator++
      ++foo_; return *this; }
  
    base operator+=(base const& o) { // base::operator+=
      foo_ += o.foo_; return *this; }
  
    int operator- (base const& o) const { // base::operator-
      return foo_ - o.foo_; }
  
    base operator-- (void) { // base::operator--
      --foo_; return *this; }
  
    base operator-= (base const& o) { // base::operator-=
      foo_ -= o.foo_; return *this; }
  
    int operator* (base const& o) const { // base::operator*
      return foo_ * o.foo_; }
  
    base operator*= (base const& o) { // base::operator*=
      foo_ *= o.foo_; return *this; }
  
    int operator/ (base const& o) const { // base::operator/
      return foo_ / o.foo_; }
  
    base operator/= (base const& o) { // base::operator/=
      foo_ /= o.foo_; return *this; }
  
    int operator% (base const& o) const { // base::operator%
      return foo_ % o.foo_; }
    
    base operator%= (base const& o) { // base::operator%=
      foo_ %= o.foo_; return *this; }
  
    bool operator< (base const& o) const { // base::operator<
      return foo_ < o.foo_; }
  
    bool operator<= (base const& o) const { // base::operator<=
      return foo_ <= o.foo_; }
  
    bool operator> (base const& o) const { // base::operator>
      return foo_ > o.foo_; }
  
    bool operator>= (base const& o) const { // base::operator>=
      return foo_ >= o.foo_; }
  
    bool operator!= (base const& o) const { // base::operator!=
      return foo_ != o.foo_; }
  
    bool operator== (base const& o) const { // base::operator==
      return foo_ == o.foo_; }
  
    bool operator! (void) const { // base::operator!
      return !foo_; }
  
    bool operator&& (base const& o) const { // base::operator&&
      return foo_ && o.foo_; }
  
    bool operator|| (base const& o) const { // base::operator||
      return foo_ || o.foo_; }
  
    int operator<< (int value) const { // base::operator<<
      return foo_  << value; }
  
    base operator<<= (int value) { // base::operator<<=
      foo_ <<= value; return *this; }
  
    int operator>> (int value) const { // base::operator>>
      return foo_  >> value; }
  
    base operator>>= (int value) { // base::operator>>=
      foo_ >>= value; return *this; }
  
    int operator~ (void) const { // base::operator~
      return ~foo_; }
  
    int operator& (base const& o) const { // base::operator&
      return foo_ & o.foo_; }
  
    base operator&= (base const& o) { // base::operator&=
      foo_ &= o.foo_; return *this; }
  
    int operator| (base const& o) const { // base::operator|
      return foo_ | o.foo_; }
  
    base operator|= (base const& o) { // base::operator|=
      foo_ |= o.foo_; return *this; }
    
    int operator^ (base const& o) const { // base::operator^
      return foo_ ^ o.foo_; }
  
    base operator^= (base const& o) { // base::operator^=
      foo_ ^= o.foo_; return *this; }
  
    base operator= (base const& o) { // base::operator=
      foo_ = o.foo_; return *this; }
  
    void operator() (void) const { // base::operator()
      return; }
  
    int operator[] (int idx) const { // base::operator[]
      return idx; }
  
    void* operator new (size_t size) throw () { // base::operator new
      return malloc (size); }
  
    void operator delete (void* ptr) { // base::operator delete
      free (ptr); }
  
    void* operator new[] (size_t size) throw () { // base::operator new[]
      return malloc (size); }
  
    void operator delete[] (void* ptr) { // base::operator delete[]
      free (ptr); }
  
    base const* operator-> (void) const { // base::opeartor->
      return this; }
  
    int operator->* (base const& b) const { // base::operator->*
      return foo_ * b.foo_; }
  
    operator char* () const { return const_cast<char*> ("hello"); } // base::operator char*
    operator int () const { return 21; } // base::operator int
    operator fluff* () const { return new fluff (); } // base::operator fluff*
    operator fluff** () const { return &g_fluff; } // base::operator fluff**
  };
  
  class base1 : public virtual base
  {
  public:
    base1 (void) : foo_ (21) { } // base1::base1(void)
    base1 (int a) : foo_(a) { } // base1::base1(int)
    void a_function (void) const { } // base1::a_function
  
  protected:
    int foo_;
  };
  
  class base2 : public virtual base
  {
  public:
    base2 () : foo_ (3) { } // base2::base2
  
  protected:
    void a_function (void) const { } // base2::a_function
    int foo_;
  };
  
  class derived : public base1, public base2
  {
    public:
    derived(void) : foo_ (4) { } // derived::derived
    void a_function (void) const { // derived::a_function
      this->base1::a_function ();
      this->base2::a_function ();
    }
  
    protected:
    int foo_;
  };
  
  class CV { public:
    static const int i;
    typedef int t;
    void m(t);
    void m(t) const;
    void m(t) volatile;
    void m(t) const volatile;
  };
  const int CV::i = 42;
  #ifdef __GNUC__
  # define ATTRIBUTE_USED __attribute__((used))
  #else
  # define ATTRIBUTE_USED
  #endif
  ATTRIBUTE_USED void CV::m(CV::t) {}
  ATTRIBUTE_USED void CV::m(CV::t) const {}
  ATTRIBUTE_USED void CV::m(CV::t) volatile {}
  ATTRIBUTE_USED void CV::m(CV::t) const volatile {}
  int CV_f (int x)
  {
    return x + 1;
  }
  
  int
  test_function (int argc, char* argv[]) // test_function
  { // test_function
    derived d;
    void (derived::*pfunc) (void) const = &derived::a_function;
    (d.*pfunc) ();
  
    base a (1), b (3), c (8);
    (void) a.overload ();
    (void) a.overload (static_cast<int> (0));
    (void) a.overload (static_cast<short> (0));
    (void) a.overload (static_cast<long> (0));
    (void) a.overload (static_cast<char*> (0));
    (void) a.overload (a);
  
    int r;
    r = b + c;
    ++a;
    a += b;
    r = b - c;
    --a;
    a -= b;
    r = b * c;
    a *= b;
    r = b / c;
    a /= b;
    r = b % c;
    a %= b;
    bool x = (b < c);
    x = (b <= c);
    x = (b > c);
    x = (b >= c);
    x = (b != c);
    x = (b == c);
    x = (!b);
    x = (b && c);
    x = (b || c);
    r = b << 2;
    a <<= 1;
    r = b >> 2;
    a >>= 1;
    r = ~b;
    r = b & c;
    a &= c;
    r = b | c;
    a |= c;
    r = b ^ c;
    a ^= c;
    a = c;
    a ();
    int i = a[3];
    derived* f = new derived ();
    derived* g = new derived[3];
    delete f;
    delete[] g;
    a->overload ();
    r = a->*b;
  
    tclass<char> char_tclass;
    tclass<int> int_tclass;
    tclass<short> short_tclass;
    tclass<long> long_tclass;
    tclass<base> base_tclass;
    char_tclass.do_something ();
    int_tclass.do_something ();
    short_tclass.do_something ();
    long_tclass.do_something ();
    base_tclass.do_something ();
  
    flubber<int, int, int, int, int> ();
    flubber<int, int, int, int, short> ();
    flubber<int, int, int, int, long> ();
    flubber<int, int, int, int, char> ();
    flubber<int, int, int, short, int> ();
    flubber<int, int, int, short, short> ();
    flubber<int, int, int, short, long> ();
    flubber<int, int, int, short, char> ();
    flubber<int, int, int, long, int> ();
    flubber<int, int, int, long, short> ();
    flubber<int, int, int, long, long> ();
    flubber<int, int, int, long, char> ();
    flubber<int, int, int, char, int> ();
    flubber<int, int, int, char, short> ();
    flubber<int, int, int, char, long> ();
    flubber<int, int, int, char, char> ();
    flubber<int, int, short, int, int> ();
    flubber<int, int, short, int, short> ();
    flubber<int, int, short, int, long> ();
    flubber<int, int, short, int, char> ();
    flubber<int, int, short, short, int> ();
    flubber<short, int, short, int, short> ();
    flubber<long, short, long, short, long> ();
  
    policy1 p1 (1);
    p1.function ();
    policy2 p2 (2);
    p2.function ();
    policy3 p3 (3);
    p3.function ();
    policy4 p4 (4);
    p4.function ();
  
    policyd1 pd1 (5);
    pd1.function ();
    policyd2 pd2 (6);
    pd2.function ();
    policyd3 pd3 (7);
    pd3.function ();
    policyd4 pd4 (d);
    pd4.function ();
    policyd5 pd5 (int_tclass);
    pd5.function ();
  
    base1 b1 (3);
  
    r = a;
    char* str = a;
    fluff* flp = a;
    fluff** flpp = a;
  
    CV_f(CV::i);
  
    return 0;
  }
  
  int
  main (int argc, char* argv[])
  {
    int i;
  
    /* Call the test function repeatedly, enough times for all our tests
       without running forever if something goes wrong.  */
    for (i = 0; i < 1000; i++)
      test_function (argc, argv);
  
    return 0;
  }
  