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.
This commit is contained in:
David Carlton 2003-05-20 03:56:29 +00:00
parent 916f5d137a
commit 1fcb515536
11 changed files with 399 additions and 17 deletions

View File

@ -1,3 +1,19 @@
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'

View File

@ -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) \

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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);
}
}

View File

@ -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 */

View File

@ -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>

View File

@ -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 ();
}

View File

@ -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."