mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-16 20:32:21 +08:00
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:
@ -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>
|
2003-09-25 Daniel Jacobowitz <drow@mvista.com>
|
||||||
|
|
||||||
* stack.c: Include "reggroups.h".
|
* stack.c: Include "reggroups.h".
|
||||||
|
@ -1412,7 +1412,7 @@ ada-lex.c: ada-lex.l
|
|||||||
.PRECIOUS: c-exp.tab.c
|
.PRECIOUS: c-exp.tab.c
|
||||||
c-exp.tab.o: c-exp.tab.c $(defs_h) $(gdb_string_h) $(expression_h) \
|
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) \
|
$(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
|
c-exp.tab.c: c-exp.y
|
||||||
$(SHELL) $(YLWRAP) "$(YACC)" \
|
$(SHELL) $(YLWRAP) "$(YACC)" \
|
||||||
$(srcdir)/c-exp.y y.tab.c c-exp.tmp -- $(YFLAGS)
|
$(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) \
|
valops.o: valops.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(value_h) $(frame_h) \
|
||||||
$(inferior_h) $(gdbcore_h) $(target_h) $(demangle_h) $(language_h) \
|
$(inferior_h) $(gdbcore_h) $(target_h) $(demangle_h) $(language_h) \
|
||||||
$(gdbcmd_h) $(regcache_h) $(cp_abi_h) $(block_h) $(infcall_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) \
|
valprint.o: valprint.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
|
||||||
$(value_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(language_h) \
|
$(value_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) $(language_h) \
|
||||||
$(annotate_h) $(valprint_h) $(floatformat_h) $(doublest_h)
|
$(annotate_h) $(valprint_h) $(floatformat_h) $(doublest_h)
|
||||||
|
179
gdb/c-exp.y
179
gdb/c-exp.y
@ -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 "objfiles.h" /* For have_full_symbols and have_partial_symbols */
|
||||||
#include "charset.h"
|
#include "charset.h"
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
|
#include "cp-support.h"
|
||||||
|
|
||||||
/* Flag indicating we're dealing with HP-compiled objects */
|
/* Flag indicating we're dealing with HP-compiled objects */
|
||||||
extern int hp_som_som_object_present;
|
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 <voidval> exp exp1 type_exp start variable qualified_name lcurly
|
||||||
%type <lval> rcurly
|
%type <lval> rcurly
|
||||||
%type <tval> type typebase
|
%type <tval> type typebase qualified_type
|
||||||
%type <tvec> nonempty_typelist
|
%type <tvec> nonempty_typelist
|
||||||
/* %type <bval> block */
|
/* %type <bval> block */
|
||||||
|
|
||||||
@ -595,7 +596,8 @@ qualified_name: typebase COLONCOLON name
|
|||||||
{
|
{
|
||||||
struct type *type = $1;
|
struct type *type = $1;
|
||||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
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.",
|
error ("`%s' is not defined as an aggregate type.",
|
||||||
TYPE_NAME (type));
|
TYPE_NAME (type));
|
||||||
|
|
||||||
@ -609,7 +611,8 @@ qualified_name: typebase COLONCOLON name
|
|||||||
struct type *type = $1;
|
struct type *type = $1;
|
||||||
struct stoken tmp_token;
|
struct stoken tmp_token;
|
||||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
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.",
|
error ("`%s' is not defined as an aggregate type.",
|
||||||
TYPE_NAME (type));
|
TYPE_NAME (type));
|
||||||
|
|
||||||
@ -888,6 +891,80 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
|
|||||||
{ $$ = follow_types ($2); }
|
{ $$ = follow_types ($2); }
|
||||||
| typebase const_or_volatile_or_space_identifier_noopt
|
| typebase const_or_volatile_or_space_identifier_noopt
|
||||||
{ $$ = follow_types ($1); }
|
{ $$ = 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
|
typename: TYPENAME
|
||||||
@ -1633,7 +1710,13 @@ yylex ()
|
|||||||
string to get a reasonable class/namespace spec or a
|
string to get a reasonable class/namespace spec or a
|
||||||
fully-qualified name. This is a kludge to get around the
|
fully-qualified name. This is a kludge to get around the
|
||||||
HP aCC compiler's generation of symbol names with embedded
|
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)
|
if (unquoted_expr)
|
||||||
{
|
{
|
||||||
/* Only do it if not inside single quotes */
|
/* Only do it if not inside single quotes */
|
||||||
@ -1687,92 +1770,10 @@ yylex ()
|
|||||||
|
|
||||||
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|
||||||
{
|
{
|
||||||
#if 1
|
/* NOTE: carlton/2003-09-25: There used to be code here to
|
||||||
/* Despite the following flaw, we need to keep this code enabled.
|
handle nested types. It didn't work very well. See the
|
||||||
Because we can get called from check_stub_method, if we don't
|
comment before qualified_type for more info. */
|
||||||
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 */
|
|
||||||
yylval.tsym.type = SYMBOL_TYPE (sym);
|
yylval.tsym.type = SYMBOL_TYPE (sym);
|
||||||
#endif /* not 0 */
|
|
||||||
return TYPENAME;
|
return TYPENAME;
|
||||||
}
|
}
|
||||||
if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
|
if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
|
||||||
|
@ -508,6 +508,41 @@ lookup_symbol_file (const char *name,
|
|||||||
return NULL;
|
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
|
/* Now come functions for dealing with symbols associated to
|
||||||
namespaces. (They're used to store the namespaces themselves, not
|
namespaces. (They're used to store the namespaces themselves, not
|
||||||
objects that live in the namespaces.) These symbols come in two
|
objects that live in the namespaces.) These symbols come in two
|
||||||
|
@ -97,6 +97,10 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace,
|
|||||||
const domain_enum domain,
|
const domain_enum domain,
|
||||||
struct symtab **symtab);
|
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,
|
extern void cp_check_possible_namespace_symbols (const char *name,
|
||||||
struct objfile *objfile);
|
struct objfile *objfile);
|
||||||
|
|
||||||
|
@ -408,11 +408,9 @@ evaluate_subexp_standard (struct type *expect_type,
|
|||||||
case OP_SCOPE:
|
case OP_SCOPE:
|
||||||
tem = longest_to_int (exp->elts[pc + 2].longconst);
|
tem = longest_to_int (exp->elts[pc + 2].longconst);
|
||||||
(*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1);
|
(*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1);
|
||||||
arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type,
|
arg1 = value_aggregate_elt (exp->elts[pc + 1].type,
|
||||||
0,
|
&exp->elts[pc + 3].string,
|
||||||
exp->elts[pc + 1].type,
|
noside);
|
||||||
&exp->elts[pc + 3].string,
|
|
||||||
NULL_TYPE);
|
|
||||||
if (arg1 == NULL)
|
if (arg1 == NULL)
|
||||||
error ("There is no field named %s", &exp->elts[pc + 3].string);
|
error ("There is no field named %s", &exp->elts[pc + 3].string);
|
||||||
return arg1;
|
return arg1;
|
||||||
|
@ -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>
|
2003-09-25 Richard Earnshaw <rearnsha@arm.com>
|
||||||
|
|
||||||
* lib/java.exp (java_init): Import target_alias before using it.
|
* lib/java.exp (java_init): Import target_alias before using it.
|
||||||
|
@ -75,6 +75,11 @@ namespace
|
|||||||
namespace G
|
namespace G
|
||||||
{
|
{
|
||||||
int Xg = 10;
|
int Xg = 10;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
int XgX = 11;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +95,11 @@ namespace C
|
|||||||
namespace F
|
namespace F
|
||||||
{
|
{
|
||||||
int cXf = 7;
|
int cXf = 7;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
int cXfX = 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,6 +108,11 @@ namespace C
|
|||||||
int cc = 2;
|
int cc = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace E
|
||||||
|
{
|
||||||
|
int ce = 4;
|
||||||
|
}
|
||||||
|
|
||||||
namespace D
|
namespace D
|
||||||
{
|
{
|
||||||
int cd = 3;
|
int cd = 3;
|
||||||
@ -118,14 +133,18 @@ namespace C
|
|||||||
//cc;
|
//cc;
|
||||||
C::cc;
|
C::cc;
|
||||||
cd;
|
cd;
|
||||||
|
//C::D::cd;
|
||||||
E::cde;
|
E::cde;
|
||||||
shadow;
|
shadow;
|
||||||
|
//E::ce;
|
||||||
cX;
|
cX;
|
||||||
F::cXf;
|
F::cXf;
|
||||||
|
F::cXfX;
|
||||||
X;
|
X;
|
||||||
G::Xg;
|
G::Xg;
|
||||||
//cXOtherFile;
|
//cXOtherFile;
|
||||||
//XOtherFile;
|
//XOtherFile;
|
||||||
|
G::XgX;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,11 @@
|
|||||||
# bug-gdb@prep.ai.mit.edu
|
# bug-gdb@prep.ai.mit.edu
|
||||||
|
|
||||||
# tests for namespaces
|
# 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
|
# 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
|
# which has an idiosyncratic way of emitting debug info
|
||||||
# for namespaces.
|
# for namespaces.
|
||||||
# Note: As of 2000-06-03, these pass under g++ - djb
|
# 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
|
# Access a data item inside a namespace using colons and
|
||||||
# single quotes :-(
|
# 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"
|
send_gdb "print 'AAA::c'\n"
|
||||||
gdb_expect {
|
gdb_expect {
|
||||||
-re "\\$\[0-9\]* = 0 '\\\\(0|000)'\r\n$gdb_prompt $" { pass "print 'AAA::c'" }
|
-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'" }
|
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".
|
# An object declared using "using".
|
||||||
|
|
||||||
send_gdb "print ina\n"
|
send_gdb "print ina\n"
|
||||||
@ -137,6 +149,15 @@ gdb_expect {
|
|||||||
timeout { fail "(timeout) print 'AAA::xyzq'('x')" }
|
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
|
# Break on a function in a namespace
|
||||||
|
|
||||||
send_gdb "break AAA::xyzq\n"
|
send_gdb "break AAA::xyzq\n"
|
||||||
@ -159,6 +180,15 @@ gdb_expect {
|
|||||||
timeout { fail "(timeout) print 'BBB::CCC::xyzq'('x')" }
|
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
|
# Break on a function in a nested namespace
|
||||||
|
|
||||||
send_gdb "break BBB::CCC::xyzq\n"
|
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 c" "\\$\[0-9\].* = 1"
|
||||||
gdb_test "print cc" "No symbol \"cc\" in current context."
|
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 C::cc" "\\$\[0-9\].* = 2"
|
||||||
gdb_test "print cd" "\\$\[0-9\].* = 3"
|
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 E::cde" "\\$\[0-9\].* = 5"
|
||||||
gdb_test "print shadow" "\\$\[0-9\].* = 13"
|
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 "print cOtherFile" "\\$\[0-9\].* = 316"
|
||||||
gdb_test "ptype C" "type = namespace C::C"
|
gdb_test "ptype C" "type = namespace C::C"
|
||||||
gdb_test "ptype E" "type = namespace C::D::E"
|
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 cX" "\\$\[0-9\].* = 6"
|
||||||
gdb_test "print 'F::cXf'" "\\$\[0-9\].* = 7"
|
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 X" "\\$\[0-9\].* = 9"
|
||||||
gdb_test "print 'G::Xg'" "\\$\[0-9\].* = 10"
|
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 cXOtherFile" "No symbol \"cXOtherFile\" in current context."
|
||||||
gdb_test "print XOtherFile" "No symbol \"XOtherFile\" in current context."
|
gdb_test "print XOtherFile" "No symbol \"XOtherFile\" in current context."
|
||||||
|
67
gdb/valops.c
67
gdb/valops.c
@ -41,6 +41,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "gdb_string.h"
|
#include "gdb_string.h"
|
||||||
#include "gdb_assert.h"
|
#include "gdb_assert.h"
|
||||||
|
#include "cp-support.h"
|
||||||
|
|
||||||
/* Flag indicating HP compilers were used; needed to correctly handle some
|
/* Flag indicating HP compilers were used; needed to correctly handle some
|
||||||
value operations with HP aCC code/runtime. */
|
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 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 CORE_ADDR allocate_space_in_inferior (int);
|
||||||
|
|
||||||
static struct value *cast_into_complex (struct type *, struct value *);
|
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);
|
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,
|
/* C++: Given an aggregate type CURTYPE, and a member name NAME,
|
||||||
return the address of this member as a "pointer to member"
|
return the address of this member as a "pointer to member"
|
||||||
type. If INTYPE is non-null, then it will be the type
|
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;
|
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
|
/* Given a pointer value V, find the real (RTTI) type
|
||||||
of the object it points to.
|
of the object it points to.
|
||||||
|
@ -379,11 +379,9 @@ extern struct value *value_struct_elt (struct value **argp,
|
|||||||
char *name, int *static_memfuncp,
|
char *name, int *static_memfuncp,
|
||||||
char *err);
|
char *err);
|
||||||
|
|
||||||
extern struct value *value_struct_elt_for_reference (struct type *domain,
|
extern struct value *value_aggregate_elt (struct type *curtype,
|
||||||
int offset,
|
char *name,
|
||||||
struct type *curtype,
|
enum noside noside);
|
||||||
char *name,
|
|
||||||
struct type *intype);
|
|
||||||
|
|
||||||
extern struct value *value_static_field (struct type *type, int fieldno);
|
extern struct value *value_static_field (struct type *type, int fieldno);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user