Re: [PATCH] call cp_lookup_symbol_namespace recursively to search symbols in C++ base classes

Liu, Lei
2010-11-08T01:38:31Z

[-- Attachment #1: Type: text/plain, Size: 1206 bytes --]

On 2010å¹´11æœˆ07æ—¥ 18:03, Yao Qi wrote:
> On 11/04/2010 04:52 PM, Liu, Lei wrote:
>>
>> I updated my patch to deal with this as long as the suggestions from
>> Tom and Yao.
>>
>> I think in cp_set_block_scope, we should set scope name on a block
>> regardless of whether processing_has_namespace_info has been set.
>> For the cases that we only have classes but no namespaces, we still
>> need scope information to tell us which symbols are valid in a block.
>>
>> How about this?
>
> Lei,
> It looks like your mail client eats spaces and tabs when you paste
> your patch in your mail client. Please re-submit your patch again
> with following steps,
>
> 1. Run 'git diff' to generate patch and dump it to a file, named
> "foo.patch" for example,
> 2. Add your ChangeLog entry either in patch header or replied mail.
> 3. Reply mail in this thread, and *attach* your patch in your mail,
> and send it out.
>
>> + /* Just set the scope name if we get a valid one. */
>
> Should be two spaces between "." and "*/". Please have a look at
> "16.1.3 Comments" in
> http://sourceware.org/gdb/current/onlinedocs/gdbint/Coding-Standards.html#Coding-Standards
>
>

Thanks Yao. I resubmit it.

[-- Attachment #2: enum_in_base_class.patch --]
[-- Type: text/x-patch, Size: 6198 bytes --]

2010-11-02 Lei Liu <lei.liu2@windriver.com>

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 <http://www.gnu.org/licenses/>.
+
+# 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