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
7 changed files with 456 additions and 68 deletions
|
@ -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>
|
2012-11-16 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
* main.c (gdb_datadir_provided): New static global.
|
* 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,
|
static struct symbol *lookup_symbol_file (const char *name,
|
||||||
const struct block *block,
|
const struct block *block,
|
||||||
const domain_enum domain,
|
const domain_enum domain,
|
||||||
int anonymous_namespace);
|
int anonymous_namespace,
|
||||||
|
int search);
|
||||||
|
|
||||||
static struct type *cp_lookup_transparent_type_loop (const char *name,
|
static struct type *cp_lookup_transparent_type_loop (const char *name,
|
||||||
const char *scope,
|
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
|
/* 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 *
|
static struct symbol *
|
||||||
cp_lookup_symbol_in_namespace (const char *namespace,
|
cp_lookup_symbol_in_namespace (const char *namespace,
|
||||||
const char *name,
|
const char *name,
|
||||||
const struct block *block,
|
const struct block *block,
|
||||||
const domain_enum domain)
|
const domain_enum domain, int search)
|
||||||
{
|
{
|
||||||
if (namespace[0] == '\0')
|
if (namespace[0] == '\0')
|
||||||
{
|
{
|
||||||
return lookup_symbol_file (name, block, domain, 0);
|
return lookup_symbol_file (name, block, domain, 0, search);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -285,7 +287,7 @@ cp_lookup_symbol_in_namespace (const char *namespace,
|
||||||
strcat (concatenated_name, "::");
|
strcat (concatenated_name, "::");
|
||||||
strcat (concatenated_name, name);
|
strcat (concatenated_name, name);
|
||||||
return lookup_symbol_file (concatenated_name, block, domain,
|
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. */
|
/* First, try to find the symbol in the given namespace. */
|
||||||
if (!declaration_only)
|
if (!declaration_only)
|
||||||
sym = cp_lookup_symbol_in_namespace (scope, name,
|
sym = cp_lookup_symbol_in_namespace (scope, name,
|
||||||
block, domain);
|
block, domain, 1);
|
||||||
|
|
||||||
if (sym != NULL)
|
if (sym != NULL)
|
||||||
return sym;
|
return sym;
|
||||||
|
@ -385,7 +387,7 @@ cp_lookup_symbol_imports (const char *scope,
|
||||||
? current->alias : current->declaration) == 0)
|
? current->alias : current->declaration) == 0)
|
||||||
sym = cp_lookup_symbol_in_namespace (current->import_src,
|
sym = cp_lookup_symbol_in_namespace (current->import_src,
|
||||||
current->declaration,
|
current->declaration,
|
||||||
block, domain);
|
block, domain, 1);
|
||||||
|
|
||||||
/* If this is a DECLARATION_ONLY search or a symbol was found
|
/* If this is a DECLARATION_ONLY search or a symbol was found
|
||||||
or this import statement was an import declaration, the
|
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,
|
sym = cp_lookup_symbol_in_namespace (scope,
|
||||||
current->import_src,
|
current->import_src,
|
||||||
block, domain);
|
block, domain, 1);
|
||||||
}
|
}
|
||||||
else if (current->alias == NULL)
|
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. */
|
/* First, try to find the symbol in the given namespace. */
|
||||||
sym = cp_lookup_symbol_in_namespace (scope, name,
|
sym = cp_lookup_symbol_in_namespace (scope, name,
|
||||||
block, domain);
|
block, domain, 1);
|
||||||
if (sym != NULL)
|
if (sym != NULL)
|
||||||
return sym;
|
return sym;
|
||||||
|
|
||||||
|
@ -621,19 +623,20 @@ lookup_namespace_scope (const char *name,
|
||||||
strncpy (namespace, scope, scope_len);
|
strncpy (namespace, scope, scope_len);
|
||||||
namespace[scope_len] = '\0';
|
namespace[scope_len] = '\0';
|
||||||
return cp_lookup_symbol_in_namespace (namespace, name,
|
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
|
/* Look up NAME in BLOCK's static block and in global blocks. If
|
||||||
ANONYMOUS_NAMESPACE is nonzero, the symbol in question is located
|
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. */
|
cp_lookup_symbol_nonlocal. */
|
||||||
|
|
||||||
static struct symbol *
|
static struct symbol *
|
||||||
lookup_symbol_file (const char *name,
|
lookup_symbol_file (const char *name,
|
||||||
const struct block *block,
|
const struct block *block,
|
||||||
const domain_enum domain,
|
const domain_enum domain,
|
||||||
int anonymous_namespace)
|
int anonymous_namespace, int search)
|
||||||
{
|
{
|
||||||
struct symbol *sym = NULL;
|
struct symbol *sym = NULL;
|
||||||
|
|
||||||
|
@ -657,6 +660,127 @@ lookup_symbol_file (const char *name,
|
||||||
sym = lookup_symbol_global (name, block, domain);
|
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;
|
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);
|
const char *parent_name = type_name_no_tag_or_error (saved_parent_type);
|
||||||
struct symbol *sym
|
struct symbol *sym
|
||||||
= cp_lookup_symbol_in_namespace (parent_name, nested_name,
|
= cp_lookup_symbol_in_namespace (parent_name, nested_name,
|
||||||
block, VAR_DOMAIN);
|
block, VAR_DOMAIN, 0);
|
||||||
char *concatenated_name;
|
char *concatenated_name;
|
||||||
|
|
||||||
if (sym != NULL)
|
if (sym != NULL)
|
||||||
|
@ -701,7 +825,7 @@ cp_lookup_nested_symbol (struct type *parent_type,
|
||||||
/* Now search all static file-level symbols. Not strictly
|
/* Now search all static file-level symbols. Not strictly
|
||||||
correct, but more useful than an error. We do not try to
|
correct, but more useful than an error. We do not try to
|
||||||
guess any imported namespace as even the fully specified
|
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. */
|
assumptions could make it too magic. */
|
||||||
|
|
||||||
size = strlen (parent_name) + 2 + strlen (nested_name) + 1;
|
size = strlen (parent_name) + 2 + strlen (nested_name) + 1;
|
||||||
|
@ -712,7 +836,9 @@ cp_lookup_nested_symbol (struct type *parent_type,
|
||||||
if (sym != NULL)
|
if (sym != NULL)
|
||||||
return sym;
|
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:
|
default:
|
||||||
internal_error (__FILE__, __LINE__,
|
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>
|
2012-11-14 Luis Machado <lgustavo@codesourcery.com>
|
||||||
|
|
||||||
* gdb.mi/mi-var-create-rtti.c: New file.
|
* 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 {
|
class A {
|
||||||
public:
|
public:
|
||||||
int a;
|
typedef int value_type;
|
||||||
int aa;
|
value_type a;
|
||||||
|
value_type aa;
|
||||||
|
|
||||||
A()
|
A()
|
||||||
{
|
{
|
||||||
a=1;
|
a=1;
|
||||||
aa=2;
|
aa=2;
|
||||||
}
|
}
|
||||||
int afoo();
|
value_type afoo();
|
||||||
int foo();
|
value_type foo();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
public:
|
public:
|
||||||
int b;
|
A::value_type b;
|
||||||
int bb;
|
A::value_type bb;
|
||||||
|
|
||||||
B()
|
B()
|
||||||
{
|
{
|
||||||
b=3;
|
b=3;
|
||||||
bb=4;
|
bb=4;
|
||||||
}
|
}
|
||||||
int bfoo();
|
A::value_type bfoo();
|
||||||
int foo();
|
A::value_type foo();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,48 +82,48 @@ public:
|
||||||
|
|
||||||
class D : private A, public B, protected C {
|
class D : private A, public B, protected C {
|
||||||
public:
|
public:
|
||||||
int d;
|
value_type d;
|
||||||
int dd;
|
value_type dd;
|
||||||
|
|
||||||
D()
|
D()
|
||||||
{
|
{
|
||||||
d =7;
|
d =7;
|
||||||
dd=8;
|
dd=8;
|
||||||
}
|
}
|
||||||
int dfoo();
|
value_type dfoo();
|
||||||
int foo();
|
value_type foo();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class E : public A, B, protected C {
|
class E : public A, B, protected C {
|
||||||
public:
|
public:
|
||||||
int e;
|
value_type e;
|
||||||
int ee;
|
value_type ee;
|
||||||
|
|
||||||
E()
|
E()
|
||||||
{
|
{
|
||||||
e =9;
|
e =9;
|
||||||
ee=10;
|
ee=10;
|
||||||
}
|
}
|
||||||
int efoo();
|
value_type efoo();
|
||||||
int foo();
|
value_type foo();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class F : A, public B, C {
|
class F : A, public B, C {
|
||||||
public:
|
public:
|
||||||
int f;
|
value_type f;
|
||||||
int ff;
|
value_type ff;
|
||||||
|
|
||||||
F()
|
F()
|
||||||
{
|
{
|
||||||
f =11;
|
f =11;
|
||||||
ff=12;
|
ff=12;
|
||||||
}
|
}
|
||||||
int ffoo();
|
value_type ffoo();
|
||||||
int foo();
|
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
|
class V_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -150,27 +194,27 @@ public:
|
||||||
|
|
||||||
V_derived vderived;
|
V_derived vderived;
|
||||||
|
|
||||||
int A::afoo() {
|
A::value_type A::afoo() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int B::bfoo() {
|
A::value_type B::bfoo() {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int C::cfoo() {
|
A::value_type C::cfoo() {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
int D::dfoo() {
|
D::value_type D::dfoo() {
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
int E::efoo() {
|
E::value_type E::efoo() {
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
int F::ffoo() {
|
F::value_type F::ffoo() {
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,37 +222,37 @@ int G::gfoo() {
|
||||||
return 77;
|
return 77;
|
||||||
}
|
}
|
||||||
|
|
||||||
int A::foo()
|
A::value_type A::foo()
|
||||||
{
|
{
|
||||||
return 7;
|
return 7;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int B::foo()
|
A::value_type B::foo()
|
||||||
{
|
{
|
||||||
return 8;
|
return 8;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int C::foo()
|
A::value_type C::foo()
|
||||||
{
|
{
|
||||||
return 9;
|
return 9;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int D::foo()
|
D::value_type D::foo()
|
||||||
{
|
{
|
||||||
return 10;
|
return 10;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int E::foo()
|
E::value_type E::foo()
|
||||||
{
|
{
|
||||||
return 11;
|
return 11;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int F::foo()
|
F::value_type F::foo()
|
||||||
{
|
{
|
||||||
return 12;
|
return 12;
|
||||||
|
|
||||||
|
@ -236,7 +280,9 @@ int main(void)
|
||||||
E e_instance;
|
E e_instance;
|
||||||
F f_instance;
|
F f_instance;
|
||||||
G g_instance;
|
G g_instance;
|
||||||
|
Z z_instance;
|
||||||
|
ZZ zz_instance;
|
||||||
|
|
||||||
marker1(); // marker1-returns-here
|
marker1(); // marker1-returns-here
|
||||||
|
|
||||||
a_instance.a = 20; // marker1-returns-here
|
a_instance.a = 20; // marker1-returns-here
|
||||||
|
@ -251,10 +297,15 @@ int main(void)
|
||||||
e_instance.ee =29;
|
e_instance.ee =29;
|
||||||
f_instance.f =30;
|
f_instance.f =30;
|
||||||
f_instance.ff =31;
|
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;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,18 @@ if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}]} {
|
||||||
return -1
|
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.
|
# Set it up at a breakpoint so we can play with the variable values.
|
||||||
|
|
||||||
if ![runto 'marker1'] then {
|
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 \
|
cp_test_ptype_class \
|
||||||
"a_instance" "" "class" "A" \
|
"a_instance" "" "class" "A" \
|
||||||
{
|
{
|
||||||
{ field public "int a;" }
|
{ field public "A::value_type a;" }
|
||||||
{ field public "int aa;" }
|
{ field public "A::value_type aa;" }
|
||||||
{ method public "A();" }
|
{ method public "A();" }
|
||||||
{ method public "int afoo();" }
|
{ method public "A::value_type afoo();" }
|
||||||
{ method public "int foo();" }
|
{ method public "A::value_type foo();" }
|
||||||
|
{ typedef public "typedef int value_type;" }
|
||||||
}
|
}
|
||||||
|
|
||||||
# class D
|
# class D
|
||||||
|
@ -77,11 +90,11 @@ cp_test_ptype_class \
|
||||||
{ base "private A" }
|
{ base "private A" }
|
||||||
{ base "public B" }
|
{ base "public B" }
|
||||||
{ base "protected C" }
|
{ base "protected C" }
|
||||||
{ field public "int d;" }
|
{ field public "A::value_type d;" }
|
||||||
{ field public "int dd;" }
|
{ field public "A::value_type dd;" }
|
||||||
{ method public "D();" }
|
{ method public "D();" }
|
||||||
{ method public "int dfoo();" }
|
{ method public "A::value_type dfoo();" }
|
||||||
{ method public "int foo();" }
|
{ method public "A::value_type foo();" }
|
||||||
} \
|
} \
|
||||||
"" \
|
"" \
|
||||||
{
|
{
|
||||||
|
@ -102,11 +115,11 @@ cp_test_ptype_class \
|
||||||
{ base "public A" }
|
{ base "public A" }
|
||||||
{ base "private B" }
|
{ base "private B" }
|
||||||
{ base "protected C" }
|
{ base "protected C" }
|
||||||
{ field public "int e;" }
|
{ field public "A::value_type e;" }
|
||||||
{ field public "int ee;" }
|
{ field public "A::value_type ee;" }
|
||||||
{ method public "E();" }
|
{ method public "E();" }
|
||||||
{ method public "int efoo();" }
|
{ method public "A::value_type efoo();" }
|
||||||
{ method public "int foo();" }
|
{ method public "A::value_type foo();" }
|
||||||
} \
|
} \
|
||||||
"" \
|
"" \
|
||||||
{
|
{
|
||||||
|
@ -127,11 +140,11 @@ cp_test_ptype_class \
|
||||||
{ base "private A" }
|
{ base "private A" }
|
||||||
{ base "public B" }
|
{ base "public B" }
|
||||||
{ base "private C" }
|
{ base "private C" }
|
||||||
{ field public "int f;" }
|
{ field public "A::value_type f;" }
|
||||||
{ field public "int ff;" }
|
{ field public "A::value_type ff;" }
|
||||||
{ method public "F();" }
|
{ method public "F();" }
|
||||||
{ method public "int ffoo();" }
|
{ method public "A::value_type ffoo();" }
|
||||||
{ method public "int foo();" }
|
{ method public "A::value_type foo();" }
|
||||||
}
|
}
|
||||||
|
|
||||||
# class G
|
# 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.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()"
|
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
|
# 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
|
# 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
|
# 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.
|
# path calling get_vptr_fieldno.
|
||||||
gdb_test "ptype vderived" "type = .*"
|
gdb_test "ptype vderived" "type = .*"
|
||||||
gdb_test "print vderived" " = {.* inter = 0.*x = 0}"
|
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…
Add table
Add a link
Reference in a new issue