summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Carlton <carlton@bactrian.org>2003-05-20 03:56:29 +0000
committerDavid Carlton <carlton@bactrian.org>2003-05-20 03:56:29 +0000
commit1c53488e571d7ead7f5de79c8997dc0364c1d4d7 (patch)
tree05e3decc847dc01710b9c80e26731e65e69847d9
parent5a0a3a96f8efb444296a35aa140c406b591b274d (diff)
downloadgdb-1c53488e571d7ead7f5de79c8997dc0364c1d4d7.tar.gz
2003-05-19 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-19 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.
-rw-r--r--gdb/ChangeLog16
-rw-r--r--gdb/Makefile.in2
-rw-r--r--gdb/block.c57
-rw-r--r--gdb/block.h6
-rw-r--r--gdb/c-lang.c3
-rw-r--r--gdb/config/djgpp/fnchange.lst1
-rw-r--r--gdb/cp-namespace.c191
-rw-r--r--gdb/cp-support.h18
-rw-r--r--gdb/testsuite/ChangeLog9
-rw-r--r--gdb/testsuite/gdb.c++/namespace.cc70
-rw-r--r--gdb/testsuite/gdb.c++/namespace.exp43
11 files changed, 399 insertions, 17 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8f1ab3dc211..1425ca79263 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,21 @@
2003-05-19 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-19 David Carlton <carlton@bactrian.org>
+
* language.h (struct language_defn): Add 'la_value_of_this'
and 'la_lookup_symbol_nonlocal' members.
* symtab.h: Declare basic_lookup_symbol_nonlocal,
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 197d17704f4..b01642a006b 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -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) \
diff --git a/gdb/block.c b/gdb/block.c
index 1360a1589d0..3396c8aa96c 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -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, const char *scope,
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 *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;
+}
diff --git a/gdb/block.h b/gdb/block.h
index 17c726dc17f..442fa4a86e4 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -200,13 +200,19 @@ extern struct block *block_for_pc (CORE_ADDR);
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 */
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 9f7ba8ef7e6..bdbbb54172c 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -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_language_defn =
c_value_print, /* Print a top-level value */
NULL, /* Language specific skip_trampoline */
value_of_this, /* value_of_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 */
diff --git a/gdb/config/djgpp/fnchange.lst b/gdb/config/djgpp/fnchange.lst
index 1b9fd8bf261..10287c9f894 100644
--- a/gdb/config/djgpp/fnchange.lst
+++ b/gdb/config/djgpp/fnchange.lst
@@ -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
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index 7205cf73838..a4c7b8d3570 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -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 (const char *name,
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. */
@@ -264,3 +279,177 @@ cp_copy_usings (struct using_direct *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. NAME is the natural name of the symbol that
+ we're looking for, LINKAGE_NAME (which is optional) is its linkage
+ name, BLOCK is the block that we're searching within, DOMAIN says
+ what kind of symbols we're looking for, and if SYMTAB is non-NULL,
+ we should store the symtab where we found the symbol in it. */
+
+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. Other arguments are as in
+ cp_lookup_symbol_nonlocal.
+
+ For example, if we're within a function A::B::f and looking for a
+ symbol f, this will get called with NAME = "f", SCOPE = "A::B", and
+ SCOPE_LEN = 0. It then calls itself with NAME and SCOPE the same,
+ but with SCOPE_LEN = 1. And then it calls itself with NAME and
+ SCOPE the same, but with SCOPE_LEN = 4. This third call looks for
+ "A::B::x"; if it doesn't find it, then the second call looks for
+ "A::x", and if that call fails, then the first call looks for
+ "x". */
+
+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 children, 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. Other arguments are as in
+ cp_lookup_symbol_nonlocal. */
+
+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, the symbol in question is located
+ within an anonymous namespace. Other arguments are as in
+ cp_lookup_symbol_nonlocal. */
+
+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)
+ {
+ /* Symbols defined in anonymous namespaces have external linkage
+ but should be treated as local to a single file nonetheless.
+ So we only search the current file's global block. */
+
+ 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);
+ }
+}
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 76e842b5d1f..952d6a2b17b 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -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
@@ -78,4 +81,17 @@ extern void cp_set_block_scope (const struct symbol *symbol,
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 */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 27eae486e2f..a2fb2dbec80 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2003-05-19 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.
+
2003-05-14 Jeff Johnston <jjohnstn@redhat.com>
Roland McGrath <roland@redhat.com>
diff --git a/gdb/testsuite/gdb.c++/namespace.cc b/gdb/testsuite/gdb.c++/namespace.cc
index 7667266c278..7b9a173d819 100644
--- a/gdb/testsuite/gdb.c++/namespace.cc
+++ b/gdb/testsuite/gdb.c++/namespace.cc
@@ -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 ();
}
-
-
-
-
-
diff --git a/gdb/testsuite/gdb.c++/namespace.exp b/gdb/testsuite/gdb.c++/namespace.exp
index 3e502c4b50a..f4efaf64d23 100644
--- a/gdb/testsuite/gdb.c++/namespace.exp
+++ b/gdb/testsuite/gdb.c++/namespace.exp
@@ -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."