2010-11-02 Lei Liu gdb/ * cp-namespace.c (cp_lookup_symbol_namespace): Recursively call itself. (cp_set_block_scope): Call block_set_scope if a valid scope name is given. gdb/testsuite/ * gdb.cp/enum.exp: New test case. * gdb.cp/enum1.cc: Ditto. * gdb.cp/enum2.cc: Ditto. --- --- gdb/cp-namespace.c | 38 +++++++++++++++++++++ gdb/testsuite/gdb.cp/enum.exp | 74 +++++++++++++++++++++++++++++++++++++++++ gdb/testsuite/gdb.cp/enum1.cc | 34 +++++++++++++++++++ gdb/testsuite/gdb.cp/enum2.cc | 37 ++++++++++++++++++++ 4 files changed, 183 insertions(+), 0 deletions(-) create mode 100644 gdb/testsuite/gdb.cp/enum.exp create mode 100644 gdb/testsuite/gdb.cp/enum1.cc create mode 100644 gdb/testsuite/gdb.cp/enum2.cc diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index 16f58ca..bbce580 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -214,6 +214,16 @@ cp_set_block_scope (const struct symbol *symbol, obsavestring (name, prefix_len, obstack), obstack); } + else if (processing_current_prefix != NULL + && processing_current_prefix[0] != '\0') + { + /* Just set the scope name if we get a valid one. */ + block_set_scope + (block, obsavestring (processing_current_prefix, + strlen (processing_current_prefix), + obstack), + obstack); + } } /* Test whether or not NAMESPACE looks like it mentions an anonymous @@ -513,6 +523,8 @@ cp_lookup_symbol_namespace (const char *scope, const domain_enum domain) { struct symbol *sym; + struct symbol *scope_sym; + struct type *scope_type; /* First, try to find the symbol in the given namespace. */ sym = cp_lookup_symbol_in_namespace (scope, name, block, domain); @@ -530,6 +542,32 @@ cp_lookup_symbol_namespace (const char *scope, block = BLOCK_SUPERBLOCK (block); } + /* If scope is a C++ class, we need to search all its base classes. */ + if (scope == NULL || scope[0] == '\0') + return NULL; + + scope_sym = lookup_symbol (scope, NULL, VAR_DOMAIN, NULL); + if (scope_sym == NULL) + return NULL; + + scope_type = SYMBOL_TYPE (scope_sym); + if (scope_type == NULL) + return NULL; + + scope_type = check_typedef (scope_type); + if (TYPE_CODE (scope_type) == TYPE_CODE_STRUCT) + { + int nbases = TYPE_N_BASECLASSES (scope_type); + int i; + for (i = 0; i < nbases; i++) + { + const char *base_name = TYPE_BASECLASS_NAME (scope_type, i); + sym = cp_lookup_symbol_namespace (base_name, name, block, domain); + if (sym != NULL) + return sym; + } + } + return NULL; } diff --git a/gdb/testsuite/gdb.cp/enum.exp b/gdb/testsuite/gdb.cp/enum.exp new file mode 100644 index 0000000..3d5e0f6 --- /dev/null +++ b/gdb/testsuite/gdb.cp/enum.exp @@ -0,0 +1,74 @@ +# Copyright 2010 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 . + +# Test searching enum constant symbols derived from base classes. + +if $tracelevel then { + strace $tracelevel +} + +set testfile1 enum1 +set testfile2 enum2 +set srcfile1 ${testfile1}.cc +set srcfile2 ${testfile2}.cc +set binfile1 ${objdir}/${subdir}/${testfile1} +set binfile2 ${objdir}/${subdir}/${testfile2} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${binfile1}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile2}" "${binfile2}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +if [get_compiler_info ${binfile1}] { + return -1 +} +if [get_compiler_info ${binfile2}] { + return -1 +} + +# Get things started. + +############################################ +# Test printing an enum constant symbol derived from base +# class without namespaces + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile1} + +gdb_breakpoint [gdb_get_line_number "breakpoint" $srcfile1] +gdb_run_cmd +gdb_test "print X" "= A::X" "Print enum constant X of class A" + + +############################################ +# Test printing an enum constant symbol derived from base +# class in a namespace + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile2} + +gdb_breakpoint [gdb_get_line_number "breakpoint" $srcfile2] +gdb_run_cmd +gdb_test "print X" "= N::A::X" \ + "Print enum constant X of class A in namespace N" + diff --git a/gdb/testsuite/gdb.cp/enum1.cc b/gdb/testsuite/gdb.cp/enum1.cc new file mode 100644 index 0000000..6211cea --- /dev/null +++ b/gdb/testsuite/gdb.cp/enum1.cc @@ -0,0 +1,34 @@ +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 + { + } +} + +int main() +{ + C c; + c.test(A::X); + return 0; +} + diff --git a/gdb/testsuite/gdb.cp/enum2.cc b/gdb/testsuite/gdb.cp/enum2.cc new file mode 100644 index 0000000..c864c1c --- /dev/null +++ b/gdb/testsuite/gdb.cp/enum2.cc @@ -0,0 +1,37 @@ +namespace N +{ + 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 + { + } + } +}; + +int main() +{ + N::C c; + c.test(N::A::X); + return 0; +} + -- 1.6.0.4