2003-09-25 David Carlton <carlton@kealia.com>

* c-exp.y: Include cp-support.h.  Add qualified_type.
	(yylex): Delete nested type hack; add comments.
	* cp-namespace.c (cp_lookup_nested_type): New function.
	* cp-support.h: Declare cp_lookup_nested_type.
	* eval.c (evaluate_subexp_standard): Call value_aggregate_elt
	instead of value_struct_elt_for_reference.
	* valops.c: Include cp-support.h.
	(value_aggregate_elt): New function.
	(value_namespace_elt): Ditto.
	(value_struct_elt_for_reference): Make static.
	* value.h: Delete declaration of value_struct_elt_for_reference;
	add declaration for value_aggregate_elt.
	* Makefile.in (c-exp.tab.o): Depend on $(cp_support_h).
	(valops.o): Ditto.

2003-09-25  David Carlton  <carlton@kealia.com>

	* gdb.cp/namespace.exp: Tweak comments.  Add non-quoted versions
	of some print tests, where appropriate.  Add tests for C::D::cd,
	E::ce, F::cXfX, G::XgX.
	* gdb.cp/namespace.cc: Add XgX, cXfX, ce.
This commit is contained in:
David Carlton 2003-09-25 16:39:39 +00:00
parent 594e6d67cd
commit 79c2c32df4
11 changed files with 288 additions and 103 deletions

View File

@ -1,3 +1,20 @@
2003-09-25 David Carlton <carlton@kealia.com>
* c-exp.y: Include cp-support.h. Add qualified_type.
(yylex): Delete nested type hack; add comments.
* cp-namespace.c (cp_lookup_nested_type): New function.
* cp-support.h: Declare cp_lookup_nested_type.
* eval.c (evaluate_subexp_standard): Call value_aggregate_elt
instead of value_struct_elt_for_reference.
* valops.c: Include cp-support.h.
(value_aggregate_elt): New function.
(value_namespace_elt): Ditto.
(value_struct_elt_for_reference): Make static.
* value.h: Delete declaration of value_struct_elt_for_reference;
add declaration for value_aggregate_elt.
* Makefile.in (c-exp.tab.o): Depend on $(cp_support_h).
(valops.o): Ditto.
2003-09-25 Daniel Jacobowitz <drow@mvista.com>
* stack.c: Include "reggroups.h".

View File

@ -1412,7 +1412,7 @@ ada-lex.c: ada-lex.l
.PRECIOUS: c-exp.tab.c
c-exp.tab.o: c-exp.tab.c $(defs_h) $(gdb_string_h) $(expression_h) \
$(value_h) $(parser_defs_h) $(language_h) $(c_lang_h) $(bfd_h) \
$(symfile_h) $(objfiles_h) $(charset_h) $(block_h)
$(symfile_h) $(objfiles_h) $(charset_h) $(block_h) $(cp_support_h)
c-exp.tab.c: c-exp.y
$(SHELL) $(YLWRAP) "$(YACC)" \
$(srcdir)/c-exp.y y.tab.c c-exp.tmp -- $(YFLAGS)
@ -2418,7 +2418,8 @@ valarith.o: valarith.c $(defs_h) $(value_h) $(symtab_h) $(gdbtypes_h) \
valops.o: valops.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(value_h) $(frame_h) \
$(inferior_h) $(gdbcore_h) $(target_h) $(demangle_h) $(language_h) \
$(gdbcmd_h) $(regcache_h) $(cp_abi_h) $(block_h) $(infcall_h) \
$(dictionary_h) $(cp_support_h) $(gdb_string_h) $(gdb_assert_h)
$(dictionary_h) $(cp_support_h) $(gdb_string_h) $(gdb_assert_h) \
$(cp_support_h)
valprint.o: valprint.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(language_h) \
$(annotate_h) $(valprint_h) $(floatformat_h) $(doublest_h)

View File

@ -51,6 +51,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
#include "charset.h"
#include "block.h"
#include "cp-support.h"
/* Flag indicating we're dealing with HP-compiled objects */
extern int hp_som_som_object_present;
@ -153,7 +154,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
%type <voidval> exp exp1 type_exp start variable qualified_name lcurly
%type <lval> rcurly
%type <tval> type typebase
%type <tval> type typebase qualified_type
%type <tvec> nonempty_typelist
/* %type <bval> block */
@ -595,7 +596,8 @@ qualified_name: typebase COLONCOLON name
{
struct type *type = $1;
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
&& TYPE_CODE (type) != TYPE_CODE_UNION)
&& TYPE_CODE (type) != TYPE_CODE_UNION
&& TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
error ("`%s' is not defined as an aggregate type.",
TYPE_NAME (type));
@ -609,7 +611,8 @@ qualified_name: typebase COLONCOLON name
struct type *type = $1;
struct stoken tmp_token;
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
&& TYPE_CODE (type) != TYPE_CODE_UNION)
&& TYPE_CODE (type) != TYPE_CODE_UNION
&& TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
error ("`%s' is not defined as an aggregate type.",
TYPE_NAME (type));
@ -888,6 +891,80 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
{ $$ = follow_types ($2); }
| typebase const_or_volatile_or_space_identifier_noopt
{ $$ = follow_types ($1); }
| qualified_type
;
/* FIXME: carlton/2003-09-25: This next bit leads to lots of
reduce-reduce conflicts, because the parser doesn't know whether or
not to use qualified_name or qualified_type: the rules are
identical. If the parser is parsing 'A::B::x', then, when it sees
the second '::', it knows that the expression to the left of it has
to be a type, so it uses qualified_type. But if it is parsing just
'A::B', then it doesn't have any way of knowing which rule to use,
so there's a reduce-reduce conflict; it picks qualified_name, since
that occurs earlier in this file than qualified_type.
There's no good way to fix this with the grammar as it stands; as
far as I can tell, some of the problems arise from ambiguities that
GDB introduces ('start' can be either an expression or a type), but
some of it is inherent to the nature of C++ (you want to treat the
input "(FOO)" fairly differently depending on whether FOO is an
expression or a type, and if FOO is a complex expression, this can
be hard to determine at the right time). Fortunately, it works
pretty well in most cases. For example, if you do 'ptype A::B',
where A::B is a nested type, then the parser will mistakenly
misidentify it as an expression; but evaluate_subexp will get
called with 'noside' set to EVAL_AVOID_SIDE_EFFECTS, and everything
will work out anyways. But there are situations where the parser
will get confused: the most common one that I've run into is when
you want to do
print *((A::B *) x)"
where the parser doesn't realize that A::B has to be a type until
it hits the first right paren, at which point it's too late. (The
workaround is to type "print *(('A::B' *) x)" instead.) (And
another solution is to fix our symbol-handling code so that the
user never wants to type something like that in the first place,
because we get all the types right without the user's help!)
Perhaps we could fix this by making the lexer smarter. Some of
this functionality used to be in the lexer, but in a way that
worked even less well than the current solution: that attempt
involved having the parser sometimes handle '::' and having the
lexer sometimes handle it, and without a clear division of
responsibility, it quickly degenerated into a big mess. Probably
the eventual correct solution will give more of a role to the lexer
(ideally via code that is shared between the lexer and
decode_line_1), but I'm not holding my breath waiting for somebody
to get around to cleaning this up... */
/* FIXME: carlton/2003-09-25: Currently, the only qualified type
symbols that we generate are nested namespaces. Next on my TODO
list is to generate all nested type names properly (or at least as
well as possible, assuming that we're using DWARF-2). */
qualified_type: typebase COLONCOLON name
{
struct type *type = $1;
struct type *new_type;
char *ncopy = alloca ($3.length + 1);
memcpy (ncopy, $3.ptr, $3.length);
ncopy[$3.length] = '\0';
if (TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
error ("`%s' is not defined as a namespace.",
TYPE_NAME (type));
new_type = cp_lookup_nested_type (type, ncopy,
expression_context_block);
if (new_type == NULL)
error ("No type \"%s\" in namespace \"%s\".",
ncopy, TYPE_NAME (type));
$$ = new_type;
}
;
typename: TYPENAME
@ -1633,7 +1710,13 @@ yylex ()
string to get a reasonable class/namespace spec or a
fully-qualified name. This is a kludge to get around the
HP aCC compiler's generation of symbol names with embedded
colons for namespace and nested classes. */
colons for namespace and nested classes. */
/* NOTE: carlton/2003-09-24: I don't entirely understand the
HP-specific code, either here or in linespec. Having said that,
I suspect that we're actually moving towards their model: we want
symbols whose names are fully qualified, which matches the
description above. */
if (unquoted_expr)
{
/* Only do it if not inside single quotes */
@ -1687,92 +1770,10 @@ yylex ()
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
{
#if 1
/* Despite the following flaw, we need to keep this code enabled.
Because we can get called from check_stub_method, if we don't
handle nested types then it screws many operations in any
program which uses nested types. */
/* In "A::x", if x is a member function of A and there happens
to be a type (nested or not, since the stabs don't make that
distinction) named x, then this code incorrectly thinks we
are dealing with nested types rather than a member function. */
char *p;
char *namestart;
struct symbol *best_sym;
/* Look ahead to detect nested types. This probably should be
done in the grammar, but trying seemed to introduce a lot
of shift/reduce and reduce/reduce conflicts. It's possible
that it could be done, though. Or perhaps a non-grammar, but
less ad hoc, approach would work well. */
/* Since we do not currently have any way of distinguishing
a nested type from a non-nested one (the stabs don't tell
us whether a type is nested), we just ignore the
containing type. */
p = lexptr;
best_sym = sym;
while (1)
{
/* Skip whitespace. */
while (*p == ' ' || *p == '\t' || *p == '\n')
++p;
if (*p == ':' && p[1] == ':')
{
/* Skip the `::'. */
p += 2;
/* Skip whitespace. */
while (*p == ' ' || *p == '\t' || *p == '\n')
++p;
namestart = p;
while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9')
|| (*p >= 'a' && *p <= 'z')
|| (*p >= 'A' && *p <= 'Z'))
++p;
if (p != namestart)
{
struct symbol *cur_sym;
/* As big as the whole rest of the expression, which is
at least big enough. */
char *ncopy = alloca (strlen (tmp)+strlen (namestart)+3);
char *tmp1;
tmp1 = ncopy;
memcpy (tmp1, tmp, strlen (tmp));
tmp1 += strlen (tmp);
memcpy (tmp1, "::", 2);
tmp1 += 2;
memcpy (tmp1, namestart, p - namestart);
tmp1[p - namestart] = '\0';
cur_sym = lookup_symbol (ncopy, expression_context_block,
VAR_DOMAIN, (int *) NULL,
(struct symtab **) NULL);
if (cur_sym)
{
if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
{
best_sym = cur_sym;
lexptr = p;
}
else
break;
}
else
break;
}
else
break;
}
else
break;
}
yylval.tsym.type = SYMBOL_TYPE (best_sym);
#else /* not 0 */
/* NOTE: carlton/2003-09-25: There used to be code here to
handle nested types. It didn't work very well. See the
comment before qualified_type for more info. */
yylval.tsym.type = SYMBOL_TYPE (sym);
#endif /* not 0 */
return TYPENAME;
}
if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)

View File

@ -508,6 +508,41 @@ lookup_symbol_file (const char *name,
return NULL;
}
/* Look up a type named NESTED_NAME that is nested inside the C++
class or namespace given by PARENT_TYPE, from within the context
given by BLOCK. Return NULL if there is no such nested type. */
/* FIXME: carlton/2003-09-24: For now, this only works for nested
namespaces; the patch to make this work on other sorts of nested
types is next on my TODO list. */
struct type *
cp_lookup_nested_type (struct type *parent_type,
const char *nested_name,
const struct block *block)
{
switch (TYPE_CODE (parent_type))
{
case TYPE_CODE_NAMESPACE:
{
const char *parent_name = TYPE_TAG_NAME (parent_type);
struct symbol *sym = cp_lookup_symbol_namespace (parent_name,
nested_name,
NULL,
block,
VAR_DOMAIN,
NULL);
if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
return NULL;
else
return SYMBOL_TYPE (sym);
}
default:
internal_error (__FILE__, __LINE__,
"cp_lookup_nested_type called on a non-namespace.");
}
}
/* Now come functions for dealing with symbols associated to
namespaces. (They're used to store the namespaces themselves, not
objects that live in the namespaces.) These symbols come in two

View File

@ -97,6 +97,10 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace,
const domain_enum domain,
struct symtab **symtab);
extern struct type *cp_lookup_nested_type (struct type *parent_type,
const char *nested_name,
const struct block *block);
extern void cp_check_possible_namespace_symbols (const char *name,
struct objfile *objfile);

View File

@ -408,11 +408,9 @@ evaluate_subexp_standard (struct type *expect_type,
case OP_SCOPE:
tem = longest_to_int (exp->elts[pc + 2].longconst);
(*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1);
arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type,
0,
exp->elts[pc + 1].type,
&exp->elts[pc + 3].string,
NULL_TYPE);
arg1 = value_aggregate_elt (exp->elts[pc + 1].type,
&exp->elts[pc + 3].string,
noside);
if (arg1 == NULL)
error ("There is no field named %s", &exp->elts[pc + 3].string);
return arg1;

View File

@ -1,3 +1,10 @@
2003-09-25 David Carlton <carlton@kealia.com>
* gdb.cp/namespace.exp: Tweak comments. Add non-quoted versions
of some print tests, where appropriate. Add tests for C::D::cd,
E::ce, F::cXfX, G::XgX.
* gdb.cp/namespace.cc: Add XgX, cXfX, ce.
2003-09-25 Richard Earnshaw <rearnsha@arm.com>
* lib/java.exp (java_init): Import target_alias before using it.

View File

@ -75,6 +75,11 @@ namespace
namespace G
{
int Xg = 10;
namespace
{
int XgX = 11;
}
}
}
@ -90,6 +95,11 @@ namespace C
namespace F
{
int cXf = 7;
namespace
{
int cXfX = 8;
}
}
}
@ -98,6 +108,11 @@ namespace C
int cc = 2;
}
namespace E
{
int ce = 4;
}
namespace D
{
int cd = 3;
@ -118,14 +133,18 @@ namespace C
//cc;
C::cc;
cd;
//C::D::cd;
E::cde;
shadow;
//E::ce;
cX;
F::cXf;
F::cXfX;
X;
G::Xg;
//cXOtherFile;
//XOtherFile;
G::XgX;
return;
}

View File

@ -18,11 +18,11 @@
# bug-gdb@prep.ai.mit.edu
# tests for namespaces
# Written by Satish Pai <pai@apollo.hp.com> 1997-07-23
# Originally written by Satish Pai <pai@apollo.hp.com> 1997-07-23
# This file is part of the gdb testsuite
# Note: These tests are geared to the HP aCC compiler,
# Note: The original tests were geared to the HP aCC compiler,
# which has an idiosyncratic way of emitting debug info
# for namespaces.
# Note: As of 2000-06-03, these pass under g++ - djb
@ -84,6 +84,11 @@ gdb_test "up" ".*main.*" "up from marker1"
# Access a data item inside a namespace using colons and
# single quotes :-(
# NOTE: carlton/2003-09-24: the quotes are becoming less necessary (or
# even desirable.) For tests where it should still work with quotes,
# I'm including versions both with and without quotes; for tests that
# shouldn't work with quotes, I'm only including one version.
send_gdb "print 'AAA::c'\n"
gdb_expect {
-re "\\$\[0-9\]* = 0 '\\\\(0|000)'\r\n$gdb_prompt $" { pass "print 'AAA::c'" }
@ -91,6 +96,13 @@ gdb_expect {
timeout { fail "(timeout) print 'AAA::c'" }
}
send_gdb "print AAA::c\n"
gdb_expect {
-re "\\$\[0-9\]* = 0 '\\\\(0|000)'\r\n$gdb_prompt $" { pass "print AAA::c" }
-re ".*$gdb_prompt $" { fail "print AAA::c" }
timeout { fail "(timeout) print AAA::c" }
}
# An object declared using "using".
send_gdb "print ina\n"
@ -137,6 +149,15 @@ gdb_expect {
timeout { fail "(timeout) print 'AAA::xyzq'('x')" }
}
send_gdb "print AAA::xyzq('x')\n"
gdb_expect {
-re "\\$\[0-9\]* = 97 'a'\r\n$gdb_prompt $" {
pass "print AAA::xyzq('x')"
}
-re ".*$gdb_prompt $" { fail "print AAA::xyzq('x')" }
timeout { fail "(timeout) print AAA::xyzq('x')" }
}
# Break on a function in a namespace
send_gdb "break AAA::xyzq\n"
@ -159,6 +180,15 @@ gdb_expect {
timeout { fail "(timeout) print 'BBB::CCC::xyzq'('x')" }
}
send_gdb "print BBB::CCC::xyzq('x')\n"
gdb_expect {
-re "\\$\[0-9\]* = 122 'z'\r\n$gdb_prompt $" {
pass "print BBB::CCC::xyzq('x')"
}
-re ".*$gdb_prompt $" { fail "print BBB::CCC::xyzq('x')" }
timeout { fail "(timeout) print BBB::CCC::xyzq('x')" }
}
# Break on a function in a nested namespace
send_gdb "break BBB::CCC::xyzq\n"
@ -204,9 +234,13 @@ if ![runto "C::D::marker2"] then {
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 C::cc" "\\$\[0-9\].* = 2"
gdb_test "print cd" "\\$\[0-9\].* = 3"
gdb_test "print C::D::cd" "No type \"D\" in namespace \"C::C\"."
gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5"
gdb_test "print E::cde" "\\$\[0-9\].* = 5"
gdb_test "print shadow" "\\$\[0-9\].* = 13"
gdb_test "print E::ce" "No symbol \"ce\" in namespace \"C::D::E\"."
gdb_test "print cOtherFile" "\\$\[0-9\].* = 316"
gdb_test "ptype C" "type = namespace C::C"
gdb_test "ptype E" "type = namespace C::D::E"
@ -215,7 +249,11 @@ gdb_test "ptype E" "type = namespace C::D::E"
gdb_test "print cX" "\\$\[0-9\].* = 6"
gdb_test "print 'F::cXf'" "\\$\[0-9\].* = 7"
gdb_test "print F::cXf" "\\$\[0-9\].* = 7"
gdb_test "print F::cXfX" "\\$\[0-9\].* = 8"
gdb_test "print X" "\\$\[0-9\].* = 9"
gdb_test "print 'G::Xg'" "\\$\[0-9\].* = 10"
gdb_test "print G::Xg" "\\$\[0-9\].* = 10"
gdb_test "print G::XgX" "\\$\[0-9\].* = 11"
gdb_test "print cXOtherFile" "No symbol \"cXOtherFile\" in current context."
gdb_test "print XOtherFile" "No symbol \"XOtherFile\" in current context."

View File

@ -41,6 +41,7 @@
#include <errno.h>
#include "gdb_string.h"
#include "gdb_assert.h"
#include "cp-support.h"
/* Flag indicating HP compilers were used; needed to correctly handle some
value operations with HP aCC code/runtime. */
@ -63,6 +64,17 @@ static struct value *search_struct_method (char *, struct value **,
static int check_field_in (struct type *, const char *);
static struct value *value_struct_elt_for_reference (struct type *domain,
int offset,
struct type *curtype,
char *name,
struct type *intype);
static struct value *value_namespace_elt (const struct type *curtype,
const char *name,
enum noside noside);
static CORE_ADDR allocate_space_in_inferior (int);
static struct value *cast_into_complex (struct type *, struct value *);
@ -2207,6 +2219,30 @@ check_field (struct value *arg1, const char *name)
return check_field_in (t, name);
}
/* C++: Given an aggregate type CURTYPE, and a member name NAME,
return the appropriate member. This function is used to resolve
user expressions of the form "DOMAIN::NAME". For more details on
what happens, see the comment before
value_struct_elt_for_reference. */
struct value *
value_aggregate_elt (struct type *curtype,
char *name,
enum noside noside)
{
switch (TYPE_CODE (curtype))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
return value_struct_elt_for_reference (curtype, 0, curtype, name, NULL);
case TYPE_CODE_NAMESPACE:
return value_namespace_elt (curtype, name, noside);
default:
internal_error (__FILE__, __LINE__,
"non-aggregate type in value_aggregate_elt");
}
}
/* C++: Given an aggregate type CURTYPE, and a member name NAME,
return the address of this member as a "pointer to member"
type. If INTYPE is non-null, then it will be the type
@ -2347,6 +2383,37 @@ value_struct_elt_for_reference (struct type *domain, int offset,
return 0;
}
/* C++: Return the member NAME of the namespace given by the type
CURTYPE. */
static struct value *
value_namespace_elt (const struct type *curtype,
const char *name,
enum noside noside)
{
const char *namespace_name = TYPE_TAG_NAME (curtype);
struct symbol *sym;
struct value *retval;
sym = cp_lookup_symbol_namespace (namespace_name, name, NULL,
get_selected_block (0), VAR_DOMAIN,
NULL);
if (sym == NULL)
retval = NULL;
else if ((noside == EVAL_AVOID_SIDE_EFFECTS)
&& (SYMBOL_CLASS (sym) == LOC_TYPEDEF))
retval = allocate_value (SYMBOL_TYPE (sym));
else
retval = value_of_variable (sym, get_selected_block (0));
if (retval == NULL)
error ("No symbol \"%s\" in namespace \"%s\".", name,
TYPE_TAG_NAME (curtype));
return retval;
}
/* Given a pointer value V, find the real (RTTI) type
of the object it points to.

View File

@ -379,11 +379,9 @@ extern struct value *value_struct_elt (struct value **argp,
char *name, int *static_memfuncp,
char *err);
extern struct value *value_struct_elt_for_reference (struct type *domain,
int offset,
struct type *curtype,
char *name,
struct type *intype);
extern struct value *value_aggregate_elt (struct type *curtype,
char *name,
enum noside noside);
extern struct value *value_static_field (struct type *type, int fieldno);