This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [rfa] namespace scope, take 2
- From: Elena Zannoni <ezannoni at redhat dot com>
- To: David Carlton <carlton at bactrian dot org>
- Cc: gdb-patches at sources dot redhat dot com, Daniel Jacobowitz <drow at mvista dot com>, Elena Zannoni <ezannoni at redhat dot com>
- Date: Mon, 19 May 2003 11:23:43 -0400
- Subject: Re: [rfa] namespace scope, take 2
- References: <m3addjyicq.fsf@papaya.bactrian.org>
David Carlton writes:
> Here's a new version of my namespace scope patch, using the language
> hook that I just posted an RFA for. Assuming that's okay, then is
> this okay, Daniel? I know you said that it was fine a few weeks ago,
> but I wanted to give you another chance to complain since it's going
> in a file you maintain. :-) (Except for a few functions in block.c,
> but Elena already said those were okay. Well, block_global_block is
> new to this version of the patch, but I'm sure it's
> non-controversial.) I added the extra test to namespace.exp that you
> requested.
>
> Tested on GCC 3.2, DWARF 2, i686-pc-linux-gnu; no regressions, and all
> new tests pass. Probably some of the new anonymous namespace tests
> will fail with GCC 2.95.3, becuase of a stupid difference between the
> output of the v2 and v3 demanglers, but I'm not going to worry about
> that for now, given the poor quality of namespace support in GCC
> 2.95.3. If that really bothers anybody, I can look into in in a
> subsequent patch.
>
I have a request, if you could add some more comments as to how the
search/recursive algorithm works. I.e give a A::B::x example...
block.c block.h ok.
thanks
elena
> David Carlton
> carlton@bactrian.org
>
> 2003-05-18 David Carlton <carlton@bactrian.org>
>
> Partial fix for PR c++/827.
> * cp-support.h: Include symtab.h.
> Declare cp_lookup_symbol_nonlocal, cp_lookup_symbol_namespace.
> * cp-namespace.c: Update contributors.
> (cp_lookup_symbol_nonlocal): New.
> (lookup_namespace_scope, cp_lookup_symbol_namespace)
> (lookup_symbol_file): Ditto.
> * c-lang.c (cplus_language_defn): Use cp_lookup_symbol_nonlocal.
> * block.h: Declare block_scope, block_using, block_global_block.
> * block.c (block_scope): New.
> (block_using, block_global_block): Ditto.
> * Makefile.in (cp_support_h): Depend on symtab_h.
> * config/djgpp/fnchange.lst: Add testsuite/gdb.c++/namespace1.cc.
>
> 2003-05-18 David Carlton <carlton@bactrian.org>
>
> * gdb.c++/namespace.exp: Add namespace scope and anonymous
> namespace tests.
> Bump copyright date.
> * gdb.c++/namespace.cc: Add anonymous namespace and namespace C.
> (main): Call C::D::marker2.
> * gdb.c++/namespace1.cc: New file.
>
> Index: cp-namespace.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/cp-namespace.c,v
> retrieving revision 1.1
> diff -u -p -r1.1 cp-namespace.c
> --- cp-namespace.c 15 Apr 2003 23:07:11 -0000 1.1
> +++ cp-namespace.c 18 May 2003 17:32:51 -0000
> @@ -1,7 +1,7 @@
> /* Helper routines for C++ support in GDB.
> Copyright 2003 Free Software Foundation, Inc.
>
> - Contributed by David Carlton.
> + Contributed by David Carlton and by Kealia, Inc.
>
> This file is part of GDB.
>
> @@ -52,6 +52,21 @@ static struct using_direct *cp_add_using
> static struct using_direct *cp_copy_usings (struct using_direct *using,
> struct obstack *obstack);
>
> +static struct symbol *lookup_namespace_scope (const char *name,
> + const char *linkage_name,
> + const struct block *block,
> + const domain_enum domain,
> + struct symtab **symtab,
> + const char *scope,
> + int scope_len);
> +
> +static struct symbol *lookup_symbol_file (const char *name,
> + const char *linkage_name,
> + const struct block *block,
> + const domain_enum domain,
> + struct symtab **symtab,
> + int anonymous_namespace);
> +
> /* Set up support for dealing with C++ namespace info in the current
> symtab. */
>
> @@ -262,5 +277,160 @@ cp_copy_usings (struct using_direct *usi
> xfree (using);
>
> return retval;
> + }
> +}
> +
> +/* The C++-specific version of name lookup for static and global
> + names. This makes sure that names get looked for in all namespaces
> + that are in scope. */
> +
> +struct symbol *
> +cp_lookup_symbol_nonlocal (const char *name,
> + const char *linkage_name,
> + const struct block *block,
> + const domain_enum domain,
> + struct symtab **symtab)
> +{
> + return lookup_namespace_scope (name, linkage_name, block, domain,
> + symtab, block_scope (block), 0);
> +}
> +
> +/* Lookup NAME at namespace scope (or, in C terms, in static and
> + global variables). SCOPE is the namespace that the current
> + function is defined within; only consider namespaces whose length
> + is at least SCOPE_LEN. (This is to make the recursion easier.) */
> +
> +static struct symbol *
> +lookup_namespace_scope (const char *name,
> + const char *linkage_name,
> + const struct block *block,
> + const domain_enum domain,
> + struct symtab **symtab,
> + const char *scope,
> + int scope_len)
> +{
> + char *namespace;
> +
> + if (scope[scope_len] != '\0')
> + {
> + /* Recursively search for names in child namespaces first. */
> +
> + struct symbol *sym;
> + int new_scope_len = scope_len;
> +
> + /* If the current scope is followed by "::", skip past that. */
> + if (new_scope_len != 0)
> + {
> + gdb_assert (scope[new_scope_len] == ':');
> + new_scope_len += 2;
> + }
> + new_scope_len += cp_find_first_component (scope + new_scope_len);
> + sym = lookup_namespace_scope (name, linkage_name, block,
> + domain, symtab,
> + scope, new_scope_len);
> + if (sym != NULL)
> + return sym;
> + }
> +
> + /* Okay, we didn't find a match in our parents, so look for the name
> + in the current namespace. */
> +
> + namespace = alloca (scope_len + 1);
> + strncpy (namespace, scope, scope_len);
> + namespace[scope_len] = '\0';
> + return cp_lookup_symbol_namespace (namespace, name, linkage_name,
> + block, domain, symtab);
> +}
> +
> +/* Look up NAME in the C++ namespace NAMESPACE, applying the using
> + directives that are active in BLOCK. Otherwise, arguments are as
> + in lookup_symbol_aux. */
> +
> +struct symbol *
> +cp_lookup_symbol_namespace (const char *namespace,
> + const char *name,
> + const char *linkage_name,
> + const struct block *block,
> + const domain_enum domain,
> + struct symtab **symtab)
> +{
> + const struct using_direct *current;
> + struct symbol *sym;
> +
> + /* First, go through the using directives. If any of them add new
> + names to the namespace we're searching in, see if we can find a
> + match by applying them. */
> +
> + for (current = block_using (block);
> + current != NULL;
> + current = current->next)
> + {
> + if (strcmp (namespace, current->outer) == 0)
> + {
> + sym = cp_lookup_symbol_namespace (current->inner,
> + name,
> + linkage_name,
> + block,
> + domain,
> + symtab);
> + if (sym != NULL)
> + return sym;
> + }
> + }
> +
> + /* We didn't find anything by applying any of the using directives
> + that are still applicable; so let's see if we've got a match
> + using the current namespace. */
> +
> + if (namespace[0] == '\0')
> + {
> + return lookup_symbol_file (name, linkage_name, block,
> + domain, symtab, 0);
> + }
> + else
> + {
> + char *concatenated_name
> + = alloca (strlen (namespace) + 2 + strlen (name) + 1);
> + strcpy (concatenated_name, namespace);
> + strcat (concatenated_name, "::");
> + strcat (concatenated_name, name);
> + sym = lookup_symbol_file (concatenated_name, linkage_name,
> + block, domain, symtab,
> + cp_is_anonymous (namespace));
> + return sym;
> + }
> +}
> +
> +/* Look up NAME in BLOCK's static block and in global blocks. If
> + ANONYMOUS_NAMESPACE is nonzero, don't look in other files' global
> + blocks, just in the one belonging to this file. */
> +
> +static struct symbol *
> +lookup_symbol_file (const char *name,
> + const char *linkage_name,
> + const struct block *block,
> + const domain_enum domain,
> + struct symtab **symtab,
> + int anonymous_namespace)
> +{
> + struct symbol *sym = NULL;
> +
> + sym = lookup_symbol_static (name, linkage_name, block, domain, symtab);
> + if (sym != NULL)
> + return sym;
> +
> + if (anonymous_namespace)
> + {
> + const struct block *global_block = block_global_block (block);
> +
> + if (global_block != NULL)
> + return lookup_symbol_aux_block (name, linkage_name, global_block,
> + domain, symtab);
> + else
> + return NULL;
> + }
> + else
> + {
> + return lookup_symbol_global (name, linkage_name, domain, symtab);
> }
> }
> Index: cp-support.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/cp-support.h,v
> retrieving revision 1.2
> diff -u -p -r1.2 cp-support.h
> --- cp-support.h 15 Apr 2003 23:07:11 -0000 1.2
> +++ cp-support.h 18 May 2003 17:32:58 -0000
> @@ -24,11 +24,14 @@
> #ifndef CP_SUPPORT_H
> #define CP_SUPPORT_H
>
> +/* We need this for 'domain_enum', alas... */
> +
> +#include "symtab.h"
> +
> /* Opaque declarations. */
>
> struct obstack;
> struct block;
> -struct symbol;
>
> /* This struct is designed to store data from using directives. It
> says that names from namespace INNER should be visible within
> @@ -77,5 +80,18 @@ extern void cp_set_block_scope (const st
> struct obstack *obstack);
>
> extern void cp_scan_for_anonymous_namespaces (const struct symbol *symbol);
> +
> +extern struct symbol *cp_lookup_symbol_nonlocal (const char *name,
> + const char *linkage_name,
> + const struct block *block,
> + const domain_enum domain,
> + struct symtab **symtab);
> +
> +extern struct symbol *cp_lookup_symbol_namespace (const char *namespace,
> + const char *name,
> + const char *linkage_name,
> + const struct block *block,
> + const domain_enum domain,
> + struct symtab **symtab);
>
> #endif /* CP_SUPPORT_H */
> --- block.c 2003-05-18 10:25:54.000000000 -0700
> +++ block.c-2 2003-05-18 10:22:42.000000000 -0700
> @@ -155,8 +155,25 @@ block_for_pc (register CORE_ADDR pc)
> return block_for_pc_sect (pc, find_pc_mapped_section (pc));
> }
>
> -/* Now come some functions designed to deal with C++ namespace
> - issues. */
> +/* Now come some functions designed to deal with C++ namespace issues.
> + The accessors are safe to use even in the non-C++ case. */
> +
> +/* This returns the namespace that BLOCK is enclosed in, or "" if it
> + isn't enclosed in a namespace at all. This travels the chain of
> + superblocks looking for a scope, if necessary. */
> +
> +const char *
> +block_scope (const struct block *block)
> +{
> + for (; block != NULL; block = BLOCK_SUPERBLOCK (block))
> + {
> + if (BLOCK_NAMESPACE (block) != NULL
> + && BLOCK_NAMESPACE (block)->scope != NULL)
> + return BLOCK_NAMESPACE (block)->scope;
> + }
> +
> + return "";
> +}
>
> /* Set BLOCK's scope member to SCOPE; if needed, allocate memory via
> OBSTACK. (It won't make a copy of SCOPE, however, so that already
> @@ -171,6 +188,27 @@ block_set_scope (struct block *block, co
> BLOCK_NAMESPACE (block)->scope = scope;
> }
>
> +/* This returns the first using directives associated to BLOCK, if
> + any. */
> +
> +/* FIXME: carlton/2003-04-23: This uses the fact that we currently
> + only have using directives in static blocks, because we only
> + generate using directives from anonymous namespaces. Eventually,
> + when we support using directives everywhere, we'll want to replace
> + this by some iterator functions. */
> +
> +struct using_direct *
> +block_using (const struct block *block)
> +{
> + const struct block *static_block = block_static_block (block);
> +
> + if (static_block == NULL
> + || BLOCK_NAMESPACE (static_block) == NULL)
> + return NULL;
> + else
> + return BLOCK_NAMESPACE (static_block)->using;
> +}
> +
> /* Set BLOCK's using member to USING; if needed, allocate memory via
> OBSTACK. (It won't make a copy of USING, however, so that already
> has to be allocated correctly.) */
> @@ -214,3 +252,18 @@ block_static_block (const struct block *
>
> return block;
> }
> +
> +/* Return the static block associated to BLOCK. Return NULL if block
> + is NULL. */
> +
> +const struct block *
> +block_global_block (const struct block *block)
> +{
> + if (block == NULL)
> + return NULL;
> +
> + while (BLOCK_SUPERBLOCK (block) != NULL)
> + block = BLOCK_SUPERBLOCK (block);
> +
> + return block;
> +}
> --- block.h 2003-05-18 10:25:54.000000000 -0700
> +++ block.h-2 2003-05-18 10:22:37.000000000 -0700
> @@ -200,13 +200,19 @@ extern struct block *block_for_pc (CORE_
>
> extern struct block *block_for_pc_sect (CORE_ADDR, asection *);
>
> +extern const char *block_scope (const struct block *block);
> +
> extern void block_set_scope (struct block *block, const char *scope,
> struct obstack *obstack);
>
> +extern struct using_direct *block_using (const struct block *block);
> +
> extern void block_set_using (struct block *block,
> struct using_direct *using,
> struct obstack *obstack);
>
> extern const struct block *block_static_block (const struct block *block);
>
> +extern const struct block *block_global_block (const struct block *block);
> +
> #endif /* BLOCK_H */
> --- c-lang.c 2003-05-18 10:25:54.000000000 -0700
> +++ c-lang.c-2 2003-05-18 10:22:47.000000000 -0700
> @@ -32,6 +32,7 @@
> #include "charset.h"
> #include "gdb_string.h"
> #include "demangle.h"
> +#include "cp-support.h"
>
> extern void _initialize_c_language (void);
> static void c_emit_char (int c, struct ui_file * stream, int quoter);
> @@ -610,7 +611,7 @@ const struct language_defn cplus_languag
> c_value_print, /* Print a top-level value */
> NULL, /* Language specific skip_trampoline */
> 1, /* lookup_symbol_this */
> - basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
> + cp_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
> cplus_demangle, /* Language specific symbol demangler */
> {"", "", "", ""}, /* Binary format info */
> {"0%lo", "0", "o", ""}, /* Octal format info */
> Index: Makefile.in
> ===================================================================
> RCS file: /cvs/src/src/gdb/Makefile.in,v
> retrieving revision 1.377
> diff -u -p -r1.377 Makefile.in
> --- Makefile.in 15 May 2003 22:18:42 -0000 1.377
> +++ Makefile.in 18 May 2003 17:32:43 -0000
> @@ -626,7 +626,7 @@ complaints_h = complaints.h
> completer_h = completer.h
> config_h = config.h
> cp_abi_h = cp-abi.h
> -cp_support_h = cp-support.h
> +cp_support_h = cp-support.h $(symtab_h)
> dcache_h = dcache.h
> defs_h = defs.h $(config_h) $(gdb_locale_h) $(gdb_signals_h) $(ansidecl_h) \
> $(libiberty_h) $(progress_h) $(bfd_h) $(tui_h) $(ui_file_h) $(xm_h) \
> Index: namespace.exp
> ===================================================================
> RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/namespace.exp,v
> retrieving revision 1.12
> diff -u -p -r1.12 namespace.exp
> --- namespace.exp 10 Jan 2002 20:46:16 -0000 1.12
> +++ namespace.exp 18 May 2003 17:18:06 -0000
> @@ -1,4 +1,4 @@
> -# Copyright 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
> +# Copyright 1997, 1998, 2000, 2001, 2002, 2003 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
> @@ -39,20 +39,26 @@ if { [skip_cplus_tests] } { continue }
>
> set testfile "namespace"
> set srcfile ${testfile}.cc
> +set objfile ${objdir}/${subdir}/${testfile}.o
> +set srcfile1 ${testfile}1.cc
> +set objfile1 ${objdir}/${subdir}/${testfile}1.o
> set binfile ${objdir}/${subdir}/${testfile}
>
> if [get_compiler_info ${binfile}] {
> return -1;
> }
>
> -
> -
> -if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
> - gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will a
> -utomatically fail."
> +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug c++}] != "" } {
> + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
> }
>
> +if { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${objfile1}" object {debug c++}] != "" } {
> + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
> +}
>
> +if { [gdb_compile "${objfile} ${objfile1}" "${binfile}" executable {debug c++}] != "" } {
> + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
> +}
>
> gdb_exit
> gdb_start
> @@ -186,3 +192,28 @@ gdb_expect {
> timeout { fail "(timeout) break BBB::Class::xyzq" }
> }
>
> +# Test to see if the appropriate namespaces are in scope when trying
> +# to print out stuff from within a function defined within a
> +# namespace.
> +
> +if ![runto "C::D::marker2"] then {
> + perror "couldn't run to marker2"
> + continue
> +}
> +
> +gdb_test "print c" "\\$\[0-9\].* = 1"
> +gdb_test "print cc" "No symbol \"cc\" in current context."
> +gdb_test "print 'C::cc'" "\\$\[0-9\].* = 2"
> +gdb_test "print cd" "\\$\[0-9\].* = 3"
> +gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5"
> +gdb_test "print shadow" "\\$\[0-9\].* = 13"
> +gdb_test "print cOtherFile" "\\$\[0-9\].* = 316"
> +
> +# Some anonymous namespace tests.
> +
> +gdb_test "print cX" "\\$\[0-9\].* = 6"
> +gdb_test "print 'F::cXf'" "\\$\[0-9\].* = 7"
> +gdb_test "print X" "\\$\[0-9\].* = 9"
> +gdb_test "print 'G::Xg'" "\\$\[0-9\].* = 10"
> +gdb_test "print cXOtherFile" "No symbol \"cXOtherFile\" in current context."
> +gdb_test "print XOtherFile" "No symbol \"XOtherFile\" in current context."
> Index: namespace.cc
> ===================================================================
> RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/namespace.cc,v
> retrieving revision 1.1
> diff -u -p -r1.1 namespace.cc
> --- namespace.cc 12 Jun 2000 01:31:41 -0000 1.1
> +++ namespace.cc 18 May 2003 17:17:58 -0000
> @@ -68,6 +68,70 @@ void marker1(void)
> return;
> }
>
> +namespace
> +{
> + int X = 9;
> +
> + namespace G
> + {
> + int Xg = 10;
> + }
> +}
> +
> +namespace C
> +{
> + int c = 1;
> + int shadow = 12;
> +
> + namespace
> + {
> + int cX = 6;
> +
> + namespace F
> + {
> + int cXf = 7;
> + }
> + }
> +
> + namespace C
> + {
> + int cc = 2;
> + }
> +
> + namespace D
> + {
> + int cd = 3;
> + int shadow = 13;
> +
> + namespace E
> + {
> + int cde = 5;
> + }
> +
> + void marker2 (void)
> + {
> + // NOTE: carlton/2003-04-23: I'm listing the expressions that I
> + // plan to have GDB try to print out, just to make sure that the
> + // compiler and I agree which ones should be legal! It's easy
> + // to screw up when testing the boundaries of namespace stuff.
> + c;
> + //cc;
> + C::cc;
> + cd;
> + E::cde;
> + shadow;
> + cX;
> + F::cXf;
> + X;
> + G::Xg;
> + //cXOtherFile;
> + //XOtherFile;
> +
> + return;
> + }
> +
> + }
> +}
>
> int main ()
> {
> @@ -95,9 +159,5 @@ int main ()
>
> marker1();
>
> + C::D::marker2 ();
> }
> -
> -
> -
> -
> -
> --- /dev/null 2002-08-30 16:31:37.000000000 -0700
> +++ namespace1.cc 2003-05-18 10:16:49.000000000 -0700
> @@ -0,0 +1,31 @@
> +/* Copyright 2003 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 2 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, write to the Free Software
> + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> +
> + Please email any bugs, comments, and/or additions to this file to:
> + bug-gdb@prep.ai.mit.edu */
> +
> +namespace C
> +{
> + namespace {
> + int cXOtherFile = 29;
> + };
> +
> + int cOtherFile = 316;
> +}
> +
> +namespace {
> + int XOtherFile = 317;
> +}
> Index: fnchange.lst
> ===================================================================
> RCS file: /cvs/src/src/gdb/config/djgpp/fnchange.lst,v
> retrieving revision 1.48
> diff -u -p -r1.48 fnchange.lst
> --- fnchange.lst 12 May 2003 00:26:18 -0000 1.48
> +++ fnchange.lst 18 May 2003 17:19:34 -0000
> @@ -244,6 +244,7 @@
> @V@/gdb/testsuite/gdb.c++/misc.cc @V@/gdb/testsuite/gdb.cxx/misc.cc
> @V@/gdb/testsuite/gdb.c++/misc.exp @V@/gdb/testsuite/gdb.cxx/misc.exp
> @V@/gdb/testsuite/gdb.c++/namespace.cc @V@/gdb/testsuite/gdb.cxx/namespace.cc
> +@V@/gdb/testsuite/gdb.c++/namespace1.cc @V@/gdb/testsuite/gdb.cxx/namesp1.cc
> @V@/gdb/testsuite/gdb.c++/namespace.exp @V@/gdb/testsuite/gdb.cxx/namespace.exp
> @V@/gdb/testsuite/gdb.c++/overload.cc @V@/gdb/testsuite/gdb.cxx/overload.cc
> @V@/gdb/testsuite/gdb.c++/overload.exp @V@/gdb/testsuite/gdb.cxx/overload.exp