gdb
PR c++/8693, PR c++/9496: * cp-namespace.c (cp_lookup_nested_type): Handle TYPE_CODE_UNION. * c-exp.y (lex_one_token): Rename from yylex. Don't call write_dollar_variable. Don't try to classify NAME tokens. (token_and_value): New type. (token_fifo, popping, name_obstack): New globals. (classify_name): New function. (classify_inner_name): Likewise. (yylex): Likewise. (VARIABLE): Now has type sval. (exp : VARIABLE): Call write_dollar_variable. (qualified_name): Use TYPENAME, not typebase. Add production for multiple "::" instances. (variable): Use name_not_typename. (qualified_type): Remove. (typebase): Update. gdb/testsuite PR c++/8693, PR c++/9496: * gdb.cp/namespace.exp: Remove some setup_kfail calls. Added regression tests.
This commit is contained in:
parent
629d6a470a
commit
48e32051ca
5 changed files with 290 additions and 155 deletions
|
@ -1,3 +1,22 @@
|
|||
2010-02-19 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
PR c++/8693, PR c++/9496:
|
||||
* cp-namespace.c (cp_lookup_nested_type): Handle TYPE_CODE_UNION.
|
||||
* c-exp.y (lex_one_token): Rename from yylex. Don't call
|
||||
write_dollar_variable. Don't try to classify NAME tokens.
|
||||
(token_and_value): New type.
|
||||
(token_fifo, popping, name_obstack): New globals.
|
||||
(classify_name): New function.
|
||||
(classify_inner_name): Likewise.
|
||||
(yylex): Likewise.
|
||||
(VARIABLE): Now has type sval.
|
||||
(exp : VARIABLE): Call write_dollar_variable.
|
||||
(qualified_name): Use TYPENAME, not typebase. Add production for
|
||||
multiple "::" instances.
|
||||
(variable): Use name_not_typename.
|
||||
(qualified_type): Remove.
|
||||
(typebase): Update.
|
||||
|
||||
2010-02-19 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* symfile.c (addr_info_make_relative): Extend comment. Move SECT to
|
||||
|
|
412
gdb/c-exp.y
412
gdb/c-exp.y
|
@ -162,7 +162,7 @@ static struct stoken operator_stoken (const char *);
|
|||
|
||||
%type <voidval> exp exp1 type_exp start variable qualified_name lcurly
|
||||
%type <lval> rcurly
|
||||
%type <tval> type typebase qualified_type
|
||||
%type <tval> type typebase
|
||||
%type <tvec> nonempty_typelist
|
||||
/* %type <bval> block */
|
||||
|
||||
|
@ -212,7 +212,7 @@ static struct stoken operator_stoken (const char *);
|
|||
legal basetypes. */
|
||||
%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD
|
||||
|
||||
%token <voidval> VARIABLE
|
||||
%token <sval> VARIABLE
|
||||
|
||||
%token <opcode> ASSIGN_MODIFY
|
||||
|
||||
|
@ -581,7 +581,9 @@ exp : variable
|
|||
;
|
||||
|
||||
exp : VARIABLE
|
||||
/* Already written by write_dollar_variable. */
|
||||
{
|
||||
write_dollar_variable ($1);
|
||||
}
|
||||
;
|
||||
|
||||
exp : SIZEOF '(' type ')' %prec UNARY
|
||||
|
@ -743,9 +745,9 @@ variable: block COLONCOLON name
|
|||
write_exp_elt_opcode (OP_VAR_VALUE); }
|
||||
;
|
||||
|
||||
qualified_name: typebase COLONCOLON name
|
||||
qualified_name: TYPENAME COLONCOLON name
|
||||
{
|
||||
struct type *type = $1;
|
||||
struct type *type = $1.type;
|
||||
CHECK_TYPEDEF (type);
|
||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION
|
||||
|
@ -758,9 +760,9 @@ qualified_name: typebase COLONCOLON name
|
|||
write_exp_string ($3);
|
||||
write_exp_elt_opcode (OP_SCOPE);
|
||||
}
|
||||
| typebase COLONCOLON '~' name
|
||||
| TYPENAME COLONCOLON '~' name
|
||||
{
|
||||
struct type *type = $1;
|
||||
struct type *type = $1.type;
|
||||
struct stoken tmp_token;
|
||||
CHECK_TYPEDEF (type);
|
||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||
|
@ -782,12 +784,19 @@ qualified_name: typebase COLONCOLON name
|
|||
write_exp_string (tmp_token);
|
||||
write_exp_elt_opcode (OP_SCOPE);
|
||||
}
|
||||
| TYPENAME COLONCOLON name COLONCOLON name
|
||||
{
|
||||
char *copy = copy_name ($3);
|
||||
error (_("No type \"%s\" within class "
|
||||
"or namespace \"%s\"."),
|
||||
copy, TYPE_NAME ($1.type));
|
||||
}
|
||||
;
|
||||
|
||||
variable: qualified_name
|
||||
| COLONCOLON name
|
||||
| COLONCOLON name_not_typename
|
||||
{
|
||||
char *name = copy_name ($2);
|
||||
char *name = copy_name ($2.stoken);
|
||||
struct symbol *sym;
|
||||
struct minimal_symbol *msymbol;
|
||||
|
||||
|
@ -1037,77 +1046,6 @@ 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... */
|
||||
|
||||
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_STRUCT
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION
|
||||
&& TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
|
||||
error ("`%s' is not defined as an aggregate type.",
|
||||
TYPE_NAME (type));
|
||||
|
||||
new_type = cp_lookup_nested_type (type, ncopy,
|
||||
expression_context_block);
|
||||
if (new_type == NULL)
|
||||
error ("No type \"%s\" within class or namespace \"%s\".",
|
||||
ncopy, TYPE_NAME (type));
|
||||
|
||||
$$ = new_type;
|
||||
}
|
||||
;
|
||||
|
||||
typename: TYPENAME
|
||||
|
@ -2031,7 +1969,7 @@ static int last_was_structop;
|
|||
/* Read one token, getting characters through lexptr. */
|
||||
|
||||
static int
|
||||
yylex (void)
|
||||
lex_one_token (void)
|
||||
{
|
||||
int c;
|
||||
int namelen;
|
||||
|
@ -2346,85 +2284,250 @@ yylex (void)
|
|||
}
|
||||
|
||||
if (*tokstart == '$')
|
||||
return VARIABLE;
|
||||
|
||||
if (in_parse_field && *lexptr == '\0')
|
||||
saw_name_at_eof = 1;
|
||||
return NAME;
|
||||
}
|
||||
|
||||
/* An object of this type is pushed on a FIFO by the "outer" lexer. */
|
||||
typedef struct
|
||||
{
|
||||
int token;
|
||||
union YYSTYPE value;
|
||||
} token_and_value;
|
||||
|
||||
DEF_VEC_O (token_and_value);
|
||||
|
||||
/* A FIFO of tokens that have been read but not yet returned to the
|
||||
parser. */
|
||||
static VEC (token_and_value) *token_fifo;
|
||||
|
||||
/* Non-zero if the lexer should return tokens from the FIFO. */
|
||||
static int popping;
|
||||
|
||||
/* Temporary storage for c_lex; this holds symbol names as they are
|
||||
built up. */
|
||||
static struct obstack name_obstack;
|
||||
|
||||
/* Classify a NAME token. The contents of the token are in `yylval'.
|
||||
Updates yylval and returns the new token type. BLOCK is the block
|
||||
in which lookups start; this can be NULL to mean the global
|
||||
scope. */
|
||||
static int
|
||||
classify_name (struct block *block)
|
||||
{
|
||||
struct symbol *sym;
|
||||
char *copy;
|
||||
int is_a_field_of_this = 0;
|
||||
|
||||
copy = copy_name (yylval.sval);
|
||||
|
||||
sym = lookup_symbol (copy, block, VAR_DOMAIN,
|
||||
parse_language->la_language == language_cplus
|
||||
? &is_a_field_of_this : (int *) NULL);
|
||||
|
||||
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
|
||||
{
|
||||
write_dollar_variable (yylval.sval);
|
||||
return VARIABLE;
|
||||
yylval.ssym.sym = sym;
|
||||
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
|
||||
return BLOCKNAME;
|
||||
}
|
||||
|
||||
/* Use token-type BLOCKNAME for symbols that happen to be defined as
|
||||
functions or symtabs. If this is not so, then ...
|
||||
Use token-type TYPENAME for symbols that happen to be defined
|
||||
currently as names of types; NAME for other symbols.
|
||||
The caller is not constrained to care about the distinction. */
|
||||
{
|
||||
struct symbol *sym;
|
||||
int is_a_field_of_this = 0;
|
||||
int hextype;
|
||||
else if (!sym)
|
||||
{
|
||||
/* See if it's a file name. */
|
||||
struct symtab *symtab;
|
||||
|
||||
sym = lookup_symbol (copy, expression_context_block,
|
||||
VAR_DOMAIN,
|
||||
parse_language->la_language == language_cplus
|
||||
? &is_a_field_of_this : (int *) NULL);
|
||||
/* Call lookup_symtab, not lookup_partial_symtab, in case there are
|
||||
no psymtabs (coff, xcoff, or some future change to blow away the
|
||||
psymtabs once once symbols are read). */
|
||||
if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
|
||||
{
|
||||
yylval.ssym.sym = sym;
|
||||
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
|
||||
return BLOCKNAME;
|
||||
}
|
||||
else if (!sym)
|
||||
{ /* See if it's a file name. */
|
||||
struct symtab *symtab;
|
||||
symtab = lookup_symtab (copy);
|
||||
if (symtab)
|
||||
{
|
||||
yylval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
|
||||
return FILENAME;
|
||||
}
|
||||
}
|
||||
|
||||
symtab = lookup_symtab (copy);
|
||||
|
||||
if (symtab)
|
||||
{
|
||||
yylval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
|
||||
return FILENAME;
|
||||
}
|
||||
}
|
||||
|
||||
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|
||||
{
|
||||
/* 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);
|
||||
return TYPENAME;
|
||||
}
|
||||
yylval.tsym.type
|
||||
= language_lookup_primitive_type_by_name (parse_language,
|
||||
parse_gdbarch, copy);
|
||||
if (yylval.tsym.type != NULL)
|
||||
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
|
||||
{
|
||||
yylval.tsym.type = SYMBOL_TYPE (sym);
|
||||
return TYPENAME;
|
||||
}
|
||||
|
||||
/* Input names that aren't symbols but ARE valid hex numbers,
|
||||
when the input radix permits them, can be names or numbers
|
||||
depending on the parse. Note we support radixes > 16 here. */
|
||||
if (!sym
|
||||
&& ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10)
|
||||
|| (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
|
||||
{
|
||||
YYSTYPE newlval; /* Its value is ignored. */
|
||||
hextype = parse_number (tokstart, namelen, 0, &newlval);
|
||||
if (hextype == INT)
|
||||
{
|
||||
yylval.ssym.sym = sym;
|
||||
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
|
||||
return NAME_OR_INT;
|
||||
}
|
||||
}
|
||||
yylval.tsym.type
|
||||
= language_lookup_primitive_type_by_name (parse_language,
|
||||
parse_gdbarch, copy);
|
||||
if (yylval.tsym.type != NULL)
|
||||
return TYPENAME;
|
||||
|
||||
/* Any other kind of symbol */
|
||||
yylval.ssym.sym = sym;
|
||||
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
|
||||
if (in_parse_field && *lexptr == '\0')
|
||||
saw_name_at_eof = 1;
|
||||
/* Input names that aren't symbols but ARE valid hex numbers, when
|
||||
the input radix permits them, can be names or numbers depending
|
||||
on the parse. Note we support radixes > 16 here. */
|
||||
if (!sym
|
||||
&& ((copy[0] >= 'a' && copy[0] < 'a' + input_radix - 10)
|
||||
|| (copy[0] >= 'A' && copy[0] < 'A' + input_radix - 10)))
|
||||
{
|
||||
YYSTYPE newlval; /* Its value is ignored. */
|
||||
int hextype = parse_number (copy, yylval.sval.length, 0, &newlval);
|
||||
if (hextype == INT)
|
||||
{
|
||||
yylval.ssym.sym = sym;
|
||||
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
|
||||
return NAME_OR_INT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Any other kind of symbol */
|
||||
yylval.ssym.sym = sym;
|
||||
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
|
||||
return NAME;
|
||||
}
|
||||
|
||||
/* Like classify_name, but used by the inner loop of the lexer, when a
|
||||
name might have already been seen. FIRST_NAME is true if the token
|
||||
in `yylval' is the first component of a name, false otherwise. If
|
||||
this function returns NAME, it might not have updated `yylval'.
|
||||
This is ok because the caller only cares about TYPENAME. */
|
||||
static int
|
||||
classify_inner_name (struct block *block, int first_name)
|
||||
{
|
||||
struct type *type, *new_type;
|
||||
char *copy;
|
||||
|
||||
if (first_name)
|
||||
return classify_name (block);
|
||||
|
||||
type = check_typedef (yylval.tsym.type);
|
||||
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
|
||||
&& TYPE_CODE (type) != TYPE_CODE_UNION
|
||||
&& TYPE_CODE (type) != TYPE_CODE_NAMESPACE)
|
||||
/* We know the caller won't expect us to update yylval. */
|
||||
return NAME;
|
||||
}
|
||||
|
||||
copy = copy_name (yylval.tsym.stoken);
|
||||
new_type = cp_lookup_nested_type (type, copy, block);
|
||||
|
||||
if (new_type == NULL)
|
||||
/* We know the caller won't expect us to update yylval. */
|
||||
return NAME;
|
||||
|
||||
yylval.tsym.type = new_type;
|
||||
return TYPENAME;
|
||||
}
|
||||
|
||||
/* The outer level of a two-level lexer. This calls the inner lexer
|
||||
to return tokens. It then either returns these tokens, or
|
||||
aggregates them into a larger token. This lets us work around a
|
||||
problem in our parsing approach, where the parser could not
|
||||
distinguish between qualified names and qualified types at the
|
||||
right point.
|
||||
|
||||
This approach is still not ideal, because it mishandles template
|
||||
types. See the comment in lex_one_token for an example. However,
|
||||
this is still an improvement over the earlier approach, and will
|
||||
suffice until we move to better parsing technology. */
|
||||
static int
|
||||
yylex (void)
|
||||
{
|
||||
token_and_value current;
|
||||
char *name;
|
||||
int first_was_coloncolon, last_was_coloncolon, first_iter;
|
||||
|
||||
if (popping && !VEC_empty (token_and_value, token_fifo))
|
||||
{
|
||||
token_and_value tv = *VEC_index (token_and_value, token_fifo, 0);
|
||||
VEC_ordered_remove (token_and_value, token_fifo, 0);
|
||||
yylval = tv.value;
|
||||
return tv.token;
|
||||
}
|
||||
popping = 0;
|
||||
|
||||
current.token = lex_one_token ();
|
||||
if (current.token == NAME)
|
||||
current.token = classify_name (expression_context_block);
|
||||
if (parse_language->la_language != language_cplus
|
||||
|| (current.token != TYPENAME && current.token != COLONCOLON))
|
||||
return current.token;
|
||||
|
||||
first_was_coloncolon = current.token == COLONCOLON;
|
||||
last_was_coloncolon = first_was_coloncolon;
|
||||
obstack_free (&name_obstack, obstack_base (&name_obstack));
|
||||
if (!last_was_coloncolon)
|
||||
obstack_grow (&name_obstack, yylval.sval.ptr, yylval.sval.length);
|
||||
current.value = yylval;
|
||||
first_iter = 1;
|
||||
while (1)
|
||||
{
|
||||
token_and_value next;
|
||||
|
||||
next.token = lex_one_token ();
|
||||
next.value = yylval;
|
||||
|
||||
if (next.token == NAME && last_was_coloncolon)
|
||||
{
|
||||
int classification;
|
||||
|
||||
classification = classify_inner_name (first_was_coloncolon
|
||||
? NULL
|
||||
: expression_context_block,
|
||||
first_iter);
|
||||
/* We keep going until we either run out of names, or until
|
||||
we have a qualified name which is not a type. */
|
||||
if (classification != TYPENAME)
|
||||
{
|
||||
/* Push the final component and leave the loop. */
|
||||
VEC_safe_push (token_and_value, token_fifo, &next);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update the partial name we are constructing. */
|
||||
if (!first_iter)
|
||||
{
|
||||
/* We don't want to put a leading "::" into the name. */
|
||||
obstack_grow_str (&name_obstack, "::");
|
||||
}
|
||||
obstack_grow (&name_obstack, next.value.sval.ptr,
|
||||
next.value.sval.length);
|
||||
|
||||
yylval.sval.ptr = obstack_base (&name_obstack);
|
||||
yylval.sval.length = obstack_object_size (&name_obstack);
|
||||
current.value = yylval;
|
||||
current.token = classification;
|
||||
|
||||
last_was_coloncolon = 0;
|
||||
}
|
||||
else if (next.token == COLONCOLON && !last_was_coloncolon)
|
||||
last_was_coloncolon = 1;
|
||||
else
|
||||
{
|
||||
/* We've reached the end of the name. */
|
||||
VEC_safe_push (token_and_value, token_fifo, &next);
|
||||
break;
|
||||
}
|
||||
|
||||
first_iter = 0;
|
||||
}
|
||||
|
||||
popping = 1;
|
||||
|
||||
/* If we ended with a "::", insert it too. */
|
||||
if (last_was_coloncolon)
|
||||
{
|
||||
token_and_value cc;
|
||||
memset (&cc, 0, sizeof (token_and_value));
|
||||
if (first_was_coloncolon)
|
||||
{
|
||||
yylval = cc.value;
|
||||
return COLONCOLON;
|
||||
}
|
||||
cc.token = COLONCOLON;
|
||||
VEC_safe_insert (token_and_value, token_fifo, 0, &cc);
|
||||
}
|
||||
|
||||
yylval = current.value;
|
||||
yylval.sval.ptr = obstack_copy0 (&expansion_obstack,
|
||||
yylval.sval.ptr,
|
||||
yylval.sval.length);
|
||||
return current.token;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -2457,6 +2560,11 @@ c_parse (void)
|
|||
last_was_structop = 0;
|
||||
saw_name_at_eof = 0;
|
||||
|
||||
VEC_free (token_and_value, token_fifo);
|
||||
popping = 0;
|
||||
obstack_init (&name_obstack);
|
||||
make_cleanup_obstack_free (&name_obstack);
|
||||
|
||||
result = yyparse ();
|
||||
do_cleanups (back_to);
|
||||
return result;
|
||||
|
|
|
@ -540,6 +540,7 @@ cp_lookup_nested_type (struct type *parent_type,
|
|||
{
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_NAMESPACE:
|
||||
case TYPE_CODE_UNION:
|
||||
{
|
||||
/* NOTE: carlton/2003-11-10: We don't treat C++ class members
|
||||
of classes like, say, data or function members. Instead,
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2010-02-19 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
PR c++/8693, PR c++/9496:
|
||||
* gdb.cp/namespace.exp: Remove some setup_kfail calls. Added
|
||||
regression tests.
|
||||
|
||||
2010-02-19 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
Fix compatibility with m68k as.
|
||||
|
|
|
@ -241,9 +241,7 @@ gdb_test "ptype E" "type = namespace C::D::E"
|
|||
gdb_test "ptype CClass" "type = (class C::CClass \{\r\n public:|struct C::CClass \{)\r\n int x;\r\n\}"
|
||||
gdb_test "ptype CClass::NestedClass" "type = (class C::CClass::NestedClass \{\r\n public:|struct C::CClass::NestedClass \{)\r\n int y;\r\n\}"
|
||||
gdb_test "ptype NestedClass" "No symbol \"NestedClass\" in current context."
|
||||
setup_kfail "gdb/1448" "*-*-*"
|
||||
gdb_test "ptype ::C::CClass" "type = class C::CClass \{\r\n public:\r\n int x;\r\n\}"
|
||||
setup_kfail "gdb/1448" "*-*-*"
|
||||
gdb_test "ptype ::C::CClass::NestedClass" "type = class C::CClass::NestedClass \{\r\n public:\r\n int y;\r\n\}"
|
||||
setup_kfail "gdb/1448" "*-*-*"
|
||||
gdb_test "ptype ::C::NestedClass" "No symbol \"NestedClass\" in namespace \"C\"."
|
||||
|
@ -255,7 +253,6 @@ gdb_test "ptype C::NestedClass" "No symbol \"NestedClass\" in namespace \"C::C\"
|
|||
|
||||
gdb_test "print cOtherFile" "\\$\[0-9\].* = 316"
|
||||
gdb_test "ptype OtherFileClass" "type = (class C::OtherFileClass \{\r\n public:|struct C::OtherFileClass \{)\r\n int z;\r\n\}"
|
||||
setup_kfail "gdb/1448" "*-*-*"
|
||||
gdb_test "ptype ::C::OtherFileClass" "type = class C::OtherFileClass \{\r\n public:\r\n int z;\r\n\}"
|
||||
gdb_test "ptype C::OtherFileClass" "No symbol \"OtherFileClass\" in namespace \"C::C\"."
|
||||
|
||||
|
@ -274,3 +271,7 @@ gdb_test "print XOtherFile" "No symbol \"XOtherFile\" in current context."
|
|||
|
||||
# Enum tests.
|
||||
gdb_test "print AAA::ALPHA" "\\$\[0-9\].* = AAA::ALPHA"
|
||||
|
||||
# Regression tests for PR 9496.
|
||||
gdb_test "whatis ::C::CClass::NestedClass" "type = C::CClass::NestedClass"
|
||||
gdb_test "whatis ::C::CClass::NestedClass *" "type = C::CClass::NestedClass \\*"
|
||||
|
|
Loading…
Reference in a new issue