mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-15 04:31:49 +08:00
50af5481d5
PR c++/14177 - Fix parsing TYPENAME:: in parentheses. * c-exp.y (classify_inner_name): Remove caller assumptions in the function comment. Return ERROR for unresolved cases. Implement returning proper NAME. (yylex): Accept also NAME from classify_inner_name. * cp-namespace.c (cp_lookup_nested_type): Rename to ... (cp_lookup_nested_symbol): ... here. Return any found symbol, not just LOC_TYPEDEF type. * cp-support.h (cp_lookup_nested_type): Update its declaration. gdb/testsuite/ PR c++/14177 - Fix parsing TYPENAME:: in parentheses. * gdb.cp/cpexprs.cc (class CV, CV::i, ATTRIBUTE_USED, CV_f): New. (test_function): Call CV_f. * gdb.cp/cpexprs.exp (p 'CV::m(int)', p CV::m(int)) (p 'CV::m(int) const', p CV::m(int) const, p 'CV::m(int) volatile') (p CV::m(int) volatile, p 'CV::m(int) const volatile') (p CV::m(int) const volatile, p CV_f(int), p CV_f(CV::t)) (p CV_f(CV::i)): New tests.
471 lines
11 KiB
C++
471 lines
11 KiB
C++
/* This testcase is part of GDB, the GNU debugger.
|
|
|
|
Copyright 2008-2012 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;
|
|
}
|