mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-21 15:33:33 +08:00
PR c++/13615
* cp-namespace.c (cp_lookup_symbol_in_namespace): Add SEARCH parameter and pass it to lookup_symbol_file. (cp_lookup_symbol_imports): Tell cp_lookup_symbol_in_namespace to search base classes. (cp_lookup_symbol_namespace): Likewise. (lookup_namespace_scope): Likewise. (lookup_symbol_file): Add SEARCH parameter. If SEARCH is non-zero and no symbol is found, lookup the class and call cp_lookup_nested_symbol. (find_symbol_in_baseclass): New function. (cp_lookup_nested_symbol): Do not let cp_lookup_symbol_in_namespace search through base classes. Do that later when there is no global symbol match. PR c++/13615 * gdb.cp/baseenum.cc: New file. * gdb.cp/baseenum.exp: New file. * gdb.cp/derivation.cc (A): Add copyright. Add a typedef. (B): Use A::value_type instead of int. Change all references. (D): Use value_type instead of int. Change all references. (E): Likewise. (F); Likewise. (Z): New class. (ZZ): New class. (N, Base, Derived): New namespace and classes. (main): Add instances of Z and ZZ. Make sure all symbols from N are kept. * gdb.cp/derivation.exp: Update typedef changes in tests. Add tests for class typedefs both before and after starting the inferior. Add tests for searching for a typedef while stopped in a method.
This commit is contained in:
parent
e64e03922c
commit
8dea366bbe
@ -1,3 +1,20 @@
|
||||
2012-11-16 Keith Seitz <keiths@redhat.com>
|
||||
|
||||
PR c++/13615
|
||||
* cp-namespace.c (cp_lookup_symbol_in_namespace): Add SEARCH
|
||||
parameter and pass it to lookup_symbol_file.
|
||||
(cp_lookup_symbol_imports): Tell cp_lookup_symbol_in_namespace
|
||||
to search base classes.
|
||||
(cp_lookup_symbol_namespace): Likewise.
|
||||
(lookup_namespace_scope): Likewise.
|
||||
(lookup_symbol_file): Add SEARCH parameter.
|
||||
If SEARCH is non-zero and no symbol is found, lookup the class
|
||||
and call cp_lookup_nested_symbol.
|
||||
(find_symbol_in_baseclass): New function.
|
||||
(cp_lookup_nested_symbol): Do not let
|
||||
cp_lookup_symbol_in_namespace search through base classes.
|
||||
Do that later when there is no global symbol match.
|
||||
|
||||
2012-11-16 Doug Evans <dje@google.com>
|
||||
|
||||
* main.c (gdb_datadir_provided): New static global.
|
||||
|
@ -42,7 +42,8 @@ static struct symbol *lookup_namespace_scope (const char *name,
|
||||
static struct symbol *lookup_symbol_file (const char *name,
|
||||
const struct block *block,
|
||||
const domain_enum domain,
|
||||
int anonymous_namespace);
|
||||
int anonymous_namespace,
|
||||
int search);
|
||||
|
||||
static struct type *cp_lookup_transparent_type_loop (const char *name,
|
||||
const char *scope,
|
||||
@ -264,17 +265,18 @@ cp_lookup_symbol_nonlocal (const char *name,
|
||||
}
|
||||
|
||||
/* Look up NAME in the C++ namespace NAMESPACE. Other arguments are
|
||||
as in cp_lookup_symbol_nonlocal. */
|
||||
as in cp_lookup_symbol_nonlocal. If SEARCH is non-zero, search
|
||||
through base classes for a matching symbol. */
|
||||
|
||||
static struct symbol *
|
||||
cp_lookup_symbol_in_namespace (const char *namespace,
|
||||
const char *name,
|
||||
const struct block *block,
|
||||
const domain_enum domain)
|
||||
const domain_enum domain, int search)
|
||||
{
|
||||
if (namespace[0] == '\0')
|
||||
{
|
||||
return lookup_symbol_file (name, block, domain, 0);
|
||||
return lookup_symbol_file (name, block, domain, 0, search);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -285,7 +287,7 @@ cp_lookup_symbol_in_namespace (const char *namespace,
|
||||
strcat (concatenated_name, "::");
|
||||
strcat (concatenated_name, name);
|
||||
return lookup_symbol_file (concatenated_name, block, domain,
|
||||
cp_is_anonymous (namespace));
|
||||
cp_is_anonymous (namespace), search);
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,7 +343,7 @@ cp_lookup_symbol_imports (const char *scope,
|
||||
/* First, try to find the symbol in the given namespace. */
|
||||
if (!declaration_only)
|
||||
sym = cp_lookup_symbol_in_namespace (scope, name,
|
||||
block, domain);
|
||||
block, domain, 1);
|
||||
|
||||
if (sym != NULL)
|
||||
return sym;
|
||||
@ -385,7 +387,7 @@ cp_lookup_symbol_imports (const char *scope,
|
||||
? current->alias : current->declaration) == 0)
|
||||
sym = cp_lookup_symbol_in_namespace (current->import_src,
|
||||
current->declaration,
|
||||
block, domain);
|
||||
block, domain, 1);
|
||||
|
||||
/* If this is a DECLARATION_ONLY search or a symbol was found
|
||||
or this import statement was an import declaration, the
|
||||
@ -419,7 +421,7 @@ cp_lookup_symbol_imports (const char *scope,
|
||||
{
|
||||
sym = cp_lookup_symbol_in_namespace (scope,
|
||||
current->import_src,
|
||||
block, domain);
|
||||
block, domain, 1);
|
||||
}
|
||||
else if (current->alias == NULL)
|
||||
{
|
||||
@ -550,7 +552,7 @@ cp_lookup_symbol_namespace (const char *scope,
|
||||
|
||||
/* First, try to find the symbol in the given namespace. */
|
||||
sym = cp_lookup_symbol_in_namespace (scope, name,
|
||||
block, domain);
|
||||
block, domain, 1);
|
||||
if (sym != NULL)
|
||||
return sym;
|
||||
|
||||
@ -621,19 +623,20 @@ lookup_namespace_scope (const char *name,
|
||||
strncpy (namespace, scope, scope_len);
|
||||
namespace[scope_len] = '\0';
|
||||
return cp_lookup_symbol_in_namespace (namespace, name,
|
||||
block, domain);
|
||||
block, domain, 1);
|
||||
}
|
||||
|
||||
/* Look up NAME in BLOCK's static block and in global blocks. If
|
||||
ANONYMOUS_NAMESPACE is nonzero, the symbol in question is located
|
||||
within an anonymous namespace. Other arguments are as in
|
||||
within an anonymous namespace. If SEARCH is non-zero, search through
|
||||
base classes for a matching symbol. Other arguments are as in
|
||||
cp_lookup_symbol_nonlocal. */
|
||||
|
||||
static struct symbol *
|
||||
lookup_symbol_file (const char *name,
|
||||
const struct block *block,
|
||||
const domain_enum domain,
|
||||
int anonymous_namespace)
|
||||
int anonymous_namespace, int search)
|
||||
{
|
||||
struct symbol *sym = NULL;
|
||||
|
||||
@ -657,6 +660,127 @@ lookup_symbol_file (const char *name,
|
||||
sym = lookup_symbol_global (name, block, domain);
|
||||
}
|
||||
|
||||
if (sym != NULL)
|
||||
return sym;
|
||||
|
||||
if (search)
|
||||
{
|
||||
char *klass, *nested;
|
||||
unsigned int prefix_len;
|
||||
struct cleanup *cleanup;
|
||||
struct symbol *klass_sym;
|
||||
|
||||
/* A simple lookup failed. Check if the symbol was defined in
|
||||
a base class. */
|
||||
|
||||
cleanup = make_cleanup (null_cleanup, NULL);
|
||||
|
||||
/* Find the name of the class and the name of the method,
|
||||
variable, etc. */
|
||||
prefix_len = cp_entire_prefix_len (name);
|
||||
|
||||
/* If no prefix was found, search "this". */
|
||||
if (prefix_len == 0)
|
||||
{
|
||||
struct type *type;
|
||||
struct symbol *this;
|
||||
|
||||
this = lookup_language_this (language_def (language_cplus), block);
|
||||
if (this == NULL)
|
||||
{
|
||||
do_cleanups (cleanup);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
type = check_typedef (TYPE_TARGET_TYPE (SYMBOL_TYPE (this)));
|
||||
klass = xstrdup (TYPE_NAME (type));
|
||||
nested = xstrdup (name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The class name is everything up to and including PREFIX_LEN. */
|
||||
klass = savestring (name, prefix_len);
|
||||
|
||||
/* The rest of the name is everything else past the initial scope
|
||||
operator. */
|
||||
nested = xstrdup (name + prefix_len + 2);
|
||||
}
|
||||
|
||||
/* Add cleanups to free memory for these strings. */
|
||||
make_cleanup (xfree, klass);
|
||||
make_cleanup (xfree, nested);
|
||||
|
||||
/* Lookup a class named KLASS. If none is found, there is nothing
|
||||
more that can be done. */
|
||||
klass_sym = lookup_symbol_global (klass, block, domain);
|
||||
if (klass_sym == NULL)
|
||||
{
|
||||
do_cleanups (cleanup);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Look for a symbol named NESTED in this class. */
|
||||
sym = cp_lookup_nested_symbol (SYMBOL_TYPE (klass_sym), nested, block);
|
||||
do_cleanups (cleanup);
|
||||
}
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
/* Search through the base classes of PARENT_TYPE for a symbol named
|
||||
NAME in block BLOCK. */
|
||||
|
||||
static struct symbol *
|
||||
find_symbol_in_baseclass (struct type *parent_type, const char *name,
|
||||
const struct block *block)
|
||||
{
|
||||
int i;
|
||||
struct symbol *sym;
|
||||
struct cleanup *cleanup;
|
||||
char *concatenated_name;
|
||||
|
||||
sym = NULL;
|
||||
concatenated_name = NULL;
|
||||
cleanup = make_cleanup (free_current_contents, &concatenated_name);
|
||||
for (i = 0; i < TYPE_N_BASECLASSES (parent_type); ++i)
|
||||
{
|
||||
size_t len;
|
||||
const char *base_name = TYPE_BASECLASS_NAME (parent_type, i);
|
||||
|
||||
if (base_name == NULL)
|
||||
continue;
|
||||
|
||||
/* Search this particular base class. */
|
||||
sym = cp_lookup_symbol_namespace (base_name, name, block, VAR_DOMAIN);
|
||||
if (sym != NULL)
|
||||
break;
|
||||
|
||||
len = strlen (base_name) + 2 + strlen (name) + 1;
|
||||
concatenated_name = xrealloc (concatenated_name, len);
|
||||
xsnprintf (concatenated_name, len, "%s::%s", base_name, name);
|
||||
sym = lookup_symbol_static (concatenated_name, block, VAR_DOMAIN);
|
||||
|
||||
/* If there is currently no BLOCK, e.g., the inferior hasn't yet
|
||||
been started, then try searching all STATIC_BLOCK symbols in
|
||||
all objfiles. */
|
||||
if (block == NULL)
|
||||
{
|
||||
sym = lookup_static_symbol_aux (concatenated_name, VAR_DOMAIN);
|
||||
if (sym != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If this class has base classes, search them next. */
|
||||
if (TYPE_N_BASECLASSES (TYPE_BASECLASS (parent_type, i)) > 0)
|
||||
{
|
||||
sym = find_symbol_in_baseclass (TYPE_BASECLASS (parent_type, i),
|
||||
name, block);
|
||||
if (sym != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
do_cleanups (cleanup);
|
||||
return sym;
|
||||
}
|
||||
|
||||
@ -692,7 +816,7 @@ cp_lookup_nested_symbol (struct type *parent_type,
|
||||
const char *parent_name = type_name_no_tag_or_error (saved_parent_type);
|
||||
struct symbol *sym
|
||||
= cp_lookup_symbol_in_namespace (parent_name, nested_name,
|
||||
block, VAR_DOMAIN);
|
||||
block, VAR_DOMAIN, 0);
|
||||
char *concatenated_name;
|
||||
|
||||
if (sym != NULL)
|
||||
@ -701,7 +825,7 @@ cp_lookup_nested_symbol (struct type *parent_type,
|
||||
/* Now search all static file-level symbols. Not strictly
|
||||
correct, but more useful than an error. We do not try to
|
||||
guess any imported namespace as even the fully specified
|
||||
namespace seach is is already not C++ compliant and more
|
||||
namespace search is already not C++ compliant and more
|
||||
assumptions could make it too magic. */
|
||||
|
||||
size = strlen (parent_name) + 2 + strlen (nested_name) + 1;
|
||||
@ -712,7 +836,9 @@ cp_lookup_nested_symbol (struct type *parent_type,
|
||||
if (sym != NULL)
|
||||
return sym;
|
||||
|
||||
return NULL;
|
||||
/* If no matching symbols were found, try searching any
|
||||
base classes. */
|
||||
return find_symbol_in_baseclass (parent_type, nested_name, block);
|
||||
}
|
||||
default:
|
||||
internal_error (__FILE__, __LINE__,
|
||||
|
@ -1,3 +1,25 @@
|
||||
2012-11-16 Keith Seitz <keiths@redhat.com>
|
||||
|
||||
PR c++/13615
|
||||
* gdb.cp/baseenum.cc: New file.
|
||||
* gdb.cp/baseenum.exp: New file.
|
||||
* gdb.cp/derivation.cc (A): Add copyright.
|
||||
Add a typedef.
|
||||
(B): Use A::value_type instead of int. Change all references.
|
||||
(D): Use value_type instead of int. Change all references.
|
||||
(E): Likewise.
|
||||
(F); Likewise.
|
||||
(Z): New class.
|
||||
(ZZ): New class.
|
||||
(N, Base, Derived): New namespace and classes.
|
||||
(main): Add instances of Z and ZZ.
|
||||
Make sure all symbols from N are kept.
|
||||
* gdb.cp/derivation.exp: Update typedef changes in tests.
|
||||
Add tests for class typedefs both before and after starting
|
||||
the inferior.
|
||||
Add tests for searching for a typedef while stopped in a
|
||||
method.
|
||||
|
||||
2012-11-14 Luis Machado <lgustavo@codesourcery.com>
|
||||
|
||||
* gdb.mi/mi-var-create-rtti.c: New file.
|
||||
|
81
gdb/testsuite/gdb.cp/baseenum.cc
Normal file
81
gdb/testsuite/gdb.cp/baseenum.cc
Normal file
@ -0,0 +1,81 @@
|
||||
/* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright 2003-2004, 2007-2012 Free Software Foundation, Inc.
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
class A
|
||||
{
|
||||
public:
|
||||
enum E {X,Y,Z};
|
||||
};
|
||||
|
||||
class B1 : public A
|
||||
{
|
||||
};
|
||||
|
||||
class B2 : public A
|
||||
{
|
||||
};
|
||||
|
||||
class C : public B1, public B2
|
||||
{
|
||||
public:
|
||||
void test(E e);
|
||||
};
|
||||
|
||||
void C::test(E e)
|
||||
{
|
||||
if (e == X) // breakpoint 1
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace N
|
||||
{
|
||||
class A
|
||||
{
|
||||
public:
|
||||
enum E {X, Y, Z};
|
||||
};
|
||||
|
||||
class B1 {};
|
||||
class B2 : public A {};
|
||||
|
||||
class C : public B1, public B2
|
||||
{
|
||||
public:
|
||||
void test (E e);
|
||||
};
|
||||
|
||||
void
|
||||
C::test (E e)
|
||||
{
|
||||
if (e == X) // breakpoint 2
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
C c;
|
||||
c.test(A::X);
|
||||
|
||||
N::C nc;
|
||||
nc.test (N::A::X);
|
||||
return 0;
|
||||
}
|
||||
|
36
gdb/testsuite/gdb.cp/baseenum.exp
Normal file
36
gdb/testsuite/gdb.cp/baseenum.exp
Normal file
@ -0,0 +1,36 @@
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
|
||||
# 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/>.
|
||||
|
||||
# Test searching enum constant symbols derived from base classes.
|
||||
|
||||
standard_testfile .cc
|
||||
|
||||
if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} {
|
||||
return -1
|
||||
}
|
||||
|
||||
if {![runto_main]} {
|
||||
untested "could not run to main"
|
||||
return -1
|
||||
}
|
||||
|
||||
gdb_breakpoint [gdb_get_line_number "breakpoint 1" $srcfile]
|
||||
gdb_continue_to_breakpoint "breakpoint 1"
|
||||
gdb_test "print X" "= A::X" "Print enum constant X of class A"
|
||||
|
||||
gdb_breakpoint [gdb_get_line_number "breakpoint 2" $srcfile]
|
||||
gdb_continue_to_breakpoint "breakpoint 2"
|
||||
gdb_test "print X" "= N::A::X" \
|
||||
"Print enum constant X of class A in namespace N"
|
@ -1,32 +1,63 @@
|
||||
/* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright 2003-2004, 2007-2012 Free Software Foundation, Inc.
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
namespace N {
|
||||
typedef double value_type;
|
||||
struct Base { typedef int value_type; };
|
||||
struct Derived : public Base {
|
||||
void doit (void) const {
|
||||
int i = 3;
|
||||
|
||||
while (i > 0)
|
||||
--i;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class A {
|
||||
public:
|
||||
int a;
|
||||
int aa;
|
||||
typedef int value_type;
|
||||
value_type a;
|
||||
value_type aa;
|
||||
|
||||
A()
|
||||
{
|
||||
a=1;
|
||||
aa=2;
|
||||
}
|
||||
int afoo();
|
||||
int foo();
|
||||
|
||||
value_type afoo();
|
||||
value_type foo();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class B {
|
||||
public:
|
||||
int b;
|
||||
int bb;
|
||||
A::value_type b;
|
||||
A::value_type bb;
|
||||
|
||||
B()
|
||||
{
|
||||
b=3;
|
||||
bb=4;
|
||||
}
|
||||
int bfoo();
|
||||
int foo();
|
||||
A::value_type bfoo();
|
||||
A::value_type foo();
|
||||
|
||||
};
|
||||
|
||||
@ -51,48 +82,48 @@ public:
|
||||
|
||||
class D : private A, public B, protected C {
|
||||
public:
|
||||
int d;
|
||||
int dd;
|
||||
value_type d;
|
||||
value_type dd;
|
||||
|
||||
D()
|
||||
{
|
||||
d =7;
|
||||
dd=8;
|
||||
}
|
||||
int dfoo();
|
||||
int foo();
|
||||
value_type dfoo();
|
||||
value_type foo();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class E : public A, B, protected C {
|
||||
public:
|
||||
int e;
|
||||
int ee;
|
||||
value_type e;
|
||||
value_type ee;
|
||||
|
||||
E()
|
||||
{
|
||||
e =9;
|
||||
ee=10;
|
||||
}
|
||||
int efoo();
|
||||
int foo();
|
||||
value_type efoo();
|
||||
value_type foo();
|
||||
|
||||
};
|
||||
|
||||
|
||||
class F : A, public B, C {
|
||||
public:
|
||||
int f;
|
||||
int ff;
|
||||
value_type f;
|
||||
value_type ff;
|
||||
|
||||
F()
|
||||
{
|
||||
f =11;
|
||||
ff=12;
|
||||
}
|
||||
int ffoo();
|
||||
int foo();
|
||||
value_type ffoo();
|
||||
value_type foo();
|
||||
|
||||
};
|
||||
|
||||
@ -118,6 +149,19 @@ public:
|
||||
|
||||
};
|
||||
|
||||
class Z : public A
|
||||
{
|
||||
public:
|
||||
typedef float value_type;
|
||||
value_type z;
|
||||
};
|
||||
|
||||
class ZZ : public Z
|
||||
{
|
||||
public:
|
||||
value_type zz;
|
||||
};
|
||||
|
||||
class V_base
|
||||
{
|
||||
public:
|
||||
@ -150,27 +194,27 @@ public:
|
||||
|
||||
V_derived vderived;
|
||||
|
||||
int A::afoo() {
|
||||
A::value_type A::afoo() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int B::bfoo() {
|
||||
A::value_type B::bfoo() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
int C::cfoo() {
|
||||
A::value_type C::cfoo() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
int D::dfoo() {
|
||||
D::value_type D::dfoo() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
int E::efoo() {
|
||||
E::value_type E::efoo() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
int F::ffoo() {
|
||||
F::value_type F::ffoo() {
|
||||
return 6;
|
||||
}
|
||||
|
||||
@ -178,37 +222,37 @@ int G::gfoo() {
|
||||
return 77;
|
||||
}
|
||||
|
||||
int A::foo()
|
||||
A::value_type A::foo()
|
||||
{
|
||||
return 7;
|
||||
|
||||
}
|
||||
|
||||
int B::foo()
|
||||
A::value_type B::foo()
|
||||
{
|
||||
return 8;
|
||||
|
||||
}
|
||||
|
||||
int C::foo()
|
||||
A::value_type C::foo()
|
||||
{
|
||||
return 9;
|
||||
|
||||
}
|
||||
|
||||
int D::foo()
|
||||
D::value_type D::foo()
|
||||
{
|
||||
return 10;
|
||||
|
||||
}
|
||||
|
||||
int E::foo()
|
||||
E::value_type E::foo()
|
||||
{
|
||||
return 11;
|
||||
|
||||
}
|
||||
|
||||
int F::foo()
|
||||
F::value_type F::foo()
|
||||
{
|
||||
return 12;
|
||||
|
||||
@ -236,7 +280,9 @@ int main(void)
|
||||
E e_instance;
|
||||
F f_instance;
|
||||
G g_instance;
|
||||
|
||||
Z z_instance;
|
||||
ZZ zz_instance;
|
||||
|
||||
marker1(); // marker1-returns-here
|
||||
|
||||
a_instance.a = 20; // marker1-returns-here
|
||||
@ -251,10 +297,15 @@ int main(void)
|
||||
e_instance.ee =29;
|
||||
f_instance.f =30;
|
||||
f_instance.ff =31;
|
||||
|
||||
|
||||
|
||||
g_instance.g = 32;
|
||||
g_instance.gg = 33;
|
||||
z_instance.z = 34.0;
|
||||
zz_instance.zz = 35.0;
|
||||
|
||||
N::Derived dobj;
|
||||
N::Derived::value_type d = 1;
|
||||
N::value_type n = 3.0;
|
||||
dobj.doit ();
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -38,6 +38,18 @@ if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} {
|
||||
return -1
|
||||
}
|
||||
|
||||
# Check inheritance of typedefs.
|
||||
foreach klass {"A" "D" "E" "F"} {
|
||||
gdb_test "ptype ${klass}::value_type" "type = int"
|
||||
gdb_test "whatis ${klass}::value_type" "type = int"
|
||||
gdb_test "p (${klass}::value_type) 0" " = 0"
|
||||
}
|
||||
foreach klass {"Z" "ZZ"} {
|
||||
gdb_test "ptype ${klass}::value_type" "type = float"
|
||||
gdb_test "whatis ${klass}::value_type" "type = float"
|
||||
gdb_test "p (${klass}::value_type) 0" " = 0"
|
||||
}
|
||||
|
||||
# Set it up at a breakpoint so we can play with the variable values.
|
||||
|
||||
if ![runto 'marker1'] then {
|
||||
@ -56,11 +68,12 @@ gdb_test "print a_instance" "\\$\[0-9\]+ = \{a = 1, aa = 2\}" "print value of a_
|
||||
cp_test_ptype_class \
|
||||
"a_instance" "" "class" "A" \
|
||||
{
|
||||
{ field public "int a;" }
|
||||
{ field public "int aa;" }
|
||||
{ field public "A::value_type a;" }
|
||||
{ field public "A::value_type aa;" }
|
||||
{ method public "A();" }
|
||||
{ method public "int afoo();" }
|
||||
{ method public "int foo();" }
|
||||
{ method public "A::value_type afoo();" }
|
||||
{ method public "A::value_type foo();" }
|
||||
{ typedef public "typedef int value_type;" }
|
||||
}
|
||||
|
||||
# class D
|
||||
@ -77,11 +90,11 @@ cp_test_ptype_class \
|
||||
{ base "private A" }
|
||||
{ base "public B" }
|
||||
{ base "protected C" }
|
||||
{ field public "int d;" }
|
||||
{ field public "int dd;" }
|
||||
{ field public "A::value_type d;" }
|
||||
{ field public "A::value_type dd;" }
|
||||
{ method public "D();" }
|
||||
{ method public "int dfoo();" }
|
||||
{ method public "int foo();" }
|
||||
{ method public "A::value_type dfoo();" }
|
||||
{ method public "A::value_type foo();" }
|
||||
} \
|
||||
"" \
|
||||
{
|
||||
@ -102,11 +115,11 @@ cp_test_ptype_class \
|
||||
{ base "public A" }
|
||||
{ base "private B" }
|
||||
{ base "protected C" }
|
||||
{ field public "int e;" }
|
||||
{ field public "int ee;" }
|
||||
{ field public "A::value_type e;" }
|
||||
{ field public "A::value_type ee;" }
|
||||
{ method public "E();" }
|
||||
{ method public "int efoo();" }
|
||||
{ method public "int foo();" }
|
||||
{ method public "A::value_type efoo();" }
|
||||
{ method public "A::value_type foo();" }
|
||||
} \
|
||||
"" \
|
||||
{
|
||||
@ -127,11 +140,11 @@ cp_test_ptype_class \
|
||||
{ base "private A" }
|
||||
{ base "public B" }
|
||||
{ base "private C" }
|
||||
{ field public "int f;" }
|
||||
{ field public "int ff;" }
|
||||
{ field public "A::value_type f;" }
|
||||
{ field public "A::value_type ff;" }
|
||||
{ method public "F();" }
|
||||
{ method public "int ffoo();" }
|
||||
{ method public "int foo();" }
|
||||
{ method public "A::value_type ffoo();" }
|
||||
{ method public "A::value_type foo();" }
|
||||
}
|
||||
|
||||
# class G
|
||||
@ -193,6 +206,35 @@ gdb_test_multiple "frame" "re-selected 'main' frame after inferior call" {
|
||||
gdb_test "print g_instance.bfoo()" "\\$\[0-9\]+ = 2" "print value of g_instance.bfoo()"
|
||||
gdb_test "print g_instance.cfoo()" "\\$\[0-9\]+ = 3" "print value of g_instance.cfoo()"
|
||||
|
||||
# Check typedefs of fields
|
||||
foreach Klass {"C" "G"} {
|
||||
set klass [string tolower $Klass]
|
||||
set instance "${klass}_instance"
|
||||
set var "${instance}.$klass"
|
||||
gdb_test "whatis $var" "int"
|
||||
gdb_test "ptype $var" "int"
|
||||
}
|
||||
|
||||
foreach Klass {"A" "B" "D" "E" "F"} {
|
||||
set klass [string tolower $Klass]
|
||||
set instance "${klass}_instance"
|
||||
set var "${instance}.$klass"
|
||||
gdb_test "whatis $var" "A::value_type"
|
||||
gdb_test "ptype $var" "int"
|
||||
if {![string equal $Klass "B"]} {
|
||||
gdb_test "p (${Klass}::value_type) 0" " = 0"
|
||||
}
|
||||
}
|
||||
|
||||
foreach Klass {"Z" "ZZ"} {
|
||||
set klass [string tolower $Klass]
|
||||
set instance "${klass}_instance"
|
||||
set var "${instance}.$klass"
|
||||
gdb_test "whatis $var" "Z::value_type"
|
||||
gdb_test "ptype $var" "float"
|
||||
gdb_test "p (${Klass}::value_type) 0" " = 0"
|
||||
}
|
||||
|
||||
# This is a regression test for a bug that caused a crash when trying
|
||||
# to print the vtbl pointer. We don't care about the output so much
|
||||
# here (it is tested elsewhere), just that gdb doesn't crash. We test
|
||||
@ -200,3 +242,16 @@ gdb_test "print g_instance.cfoo()" "\\$\[0-9\]+ = 3" "print value of g_instance.
|
||||
# path calling get_vptr_fieldno.
|
||||
gdb_test "ptype vderived" "type = .*"
|
||||
gdb_test "print vderived" " = {.* inter = 0.*x = 0}"
|
||||
|
||||
# Test whether inheritance of typedefs is properly
|
||||
# reported when stopped.
|
||||
gdb_test "ptype N::value_type" "type = double"
|
||||
gdb_test "ptype N::Derived::value_type" "type = int"
|
||||
|
||||
# Now run to N::Derived::doit and get the type of "value_type"
|
||||
if {![runto "N::Derived::doit"]} {
|
||||
perrro "couldn't run to N::Derived::doit"
|
||||
continue
|
||||
}
|
||||
|
||||
gdb_test "ptype value_type" "type = int"
|
||||
|
Loading…
Reference in New Issue
Block a user