blob: e2844d52b28d56e4ddd7f1a7f37bac4c016748a2 [file] [log] [blame]
/* This testcase is part of GDB, the GNU debugger.
Copyright 2008-2021 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**
operator fluff const* const* () const { return &g_fluff; } // base::operator fluff const* const*
};
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;
fluff const* const* flcpcp = 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;
}