* ada-lang.c (ada_make_symbol_completion_list): Add 'code'

argument, assertion.
	* c-exp.y (typebase): Add completion productions.
	* completer.c (expression_completer): Handle tag completion.
	* expression.h (parse_expression_for_completion): Add argument.
	* f-lang.c (f_make_symbol_completion_list): Add 'code'
	argument.
	* language.h (struct language_defn)
	<la_make_symbol_completion_list>: Add 'code' argument.
	* parse.c (expout_tag_completion_type, expout_completion_name):
	New globals.
	(mark_struct_expression): Add assertion.
	(mark_completion_tag): New function.
	(parse_exp_in_context): Initialize new globals.
	(parse_expression_for_completion): Add 'code' argument.  Handle
	tag completion.
	* parser-defs.h (mark_completion_tag): Declare.
	* symtab.c (default_make_symbol_completion_list_break_on): Add
	'code' argument.  Update.
	(default_make_symbol_completion_list): Add 'code' argument.
	(make_symbol_completion_list): Update.
	(make_symbol_completion_type): New function.
	* symtab.h (default_make_symbol_completion_list_break_on)
	(default_make_symbol_completion_list): Update.
	(make_symbol_completion_type): Declare.
testsuite
	* gdb.base/break1.c (enum some_enum, union some_union): New.
	(some_enum_global, some_union_global, some_value): New globals.
	* gdb.base/completion.exp: Add tag completion tests.
This commit is contained in:
Tom Tromey 2012-12-07 20:09:11 +00:00
parent 155da5173d
commit 2f68a89553
14 changed files with 244 additions and 33 deletions

View File

@ -1,3 +1,31 @@
2012-12-07 Tom Tromey <tromey@redhat.com>
* ada-lang.c (ada_make_symbol_completion_list): Add 'code'
argument, assertion.
* c-exp.y (typebase): Add completion productions.
* completer.c (expression_completer): Handle tag completion.
* expression.h (parse_expression_for_completion): Add argument.
* f-lang.c (f_make_symbol_completion_list): Add 'code'
argument.
* language.h (struct language_defn)
<la_make_symbol_completion_list>: Add 'code' argument.
* parse.c (expout_tag_completion_type, expout_completion_name):
New globals.
(mark_struct_expression): Add assertion.
(mark_completion_tag): New function.
(parse_exp_in_context): Initialize new globals.
(parse_expression_for_completion): Add 'code' argument. Handle
tag completion.
* parser-defs.h (mark_completion_tag): Declare.
* symtab.c (default_make_symbol_completion_list_break_on): Add
'code' argument. Update.
(default_make_symbol_completion_list): Add 'code' argument.
(make_symbol_completion_list): Update.
(make_symbol_completion_type): New function.
* symtab.h (default_make_symbol_completion_list_break_on)
(default_make_symbol_completion_list): Update.
(make_symbol_completion_type): Declare.
2012-12-07 Tom Tromey <tromey@redhat.com> 2012-12-07 Tom Tromey <tromey@redhat.com>
* expression.h (parse_expression_for_completion): Rename * expression.h (parse_expression_for_completion): Rename

View File

@ -5802,7 +5802,7 @@ ada_expand_partial_symbol_name (const char *name, void *user_data)
the entire command on which completion is made. */ the entire command on which completion is made. */
static VEC (char_ptr) * static VEC (char_ptr) *
ada_make_symbol_completion_list (char *text0, char *word) ada_make_symbol_completion_list (char *text0, char *word, enum type_code code)
{ {
char *text; char *text;
int text_len; int text_len;
@ -5817,6 +5817,8 @@ ada_make_symbol_completion_list (char *text0, char *word)
int i; int i;
struct block_iterator iter; struct block_iterator iter;
gdb_assert (code == TYPE_CODE_UNDEF);
if (text0[0] == '<') if (text0[0] == '<')
{ {
text = xstrdup (text0); text = xstrdup (text0);

View File

@ -1268,15 +1268,59 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
| STRUCT name | STRUCT name
{ $$ = lookup_struct (copy_name ($2), { $$ = lookup_struct (copy_name ($2),
expression_context_block); } expression_context_block); }
| STRUCT COMPLETE
{
mark_completion_tag (TYPE_CODE_STRUCT, "", 0);
$$ = NULL;
}
| STRUCT name COMPLETE
{
mark_completion_tag (TYPE_CODE_STRUCT, $2.ptr,
$2.length);
$$ = NULL;
}
| CLASS name | CLASS name
{ $$ = lookup_struct (copy_name ($2), { $$ = lookup_struct (copy_name ($2),
expression_context_block); } expression_context_block); }
| CLASS COMPLETE
{
mark_completion_tag (TYPE_CODE_CLASS, "", 0);
$$ = NULL;
}
| CLASS name COMPLETE
{
mark_completion_tag (TYPE_CODE_CLASS, $2.ptr,
$2.length);
$$ = NULL;
}
| UNION name | UNION name
{ $$ = lookup_union (copy_name ($2), { $$ = lookup_union (copy_name ($2),
expression_context_block); } expression_context_block); }
| UNION COMPLETE
{
mark_completion_tag (TYPE_CODE_UNION, "", 0);
$$ = NULL;
}
| UNION name COMPLETE
{
mark_completion_tag (TYPE_CODE_UNION, $2.ptr,
$2.length);
$$ = NULL;
}
| ENUM name | ENUM name
{ $$ = lookup_enum (copy_name ($2), { $$ = lookup_enum (copy_name ($2),
expression_context_block); } expression_context_block); }
| ENUM COMPLETE
{
mark_completion_tag (TYPE_CODE_ENUM, "", 0);
$$ = NULL;
}
| ENUM name COMPLETE
{
mark_completion_tag (TYPE_CODE_ENUM, $2.ptr,
$2.length);
$$ = NULL;
}
| UNSIGNED typename | UNSIGNED typename
{ $$ = lookup_unsigned_typename (parse_language, { $$ = lookup_unsigned_typename (parse_language,
parse_gdbarch, parse_gdbarch,

View File

@ -390,13 +390,14 @@ expression_completer (struct cmd_list_element *ignore,
struct type *type = NULL; struct type *type = NULL;
char *fieldname, *p; char *fieldname, *p;
volatile struct gdb_exception except; volatile struct gdb_exception except;
enum type_code code = TYPE_CODE_UNDEF;
/* Perform a tentative parse of the expression, to see whether a /* Perform a tentative parse of the expression, to see whether a
field completion is required. */ field completion is required. */
fieldname = NULL; fieldname = NULL;
TRY_CATCH (except, RETURN_MASK_ERROR) TRY_CATCH (except, RETURN_MASK_ERROR)
{ {
type = parse_expression_for_completion (text, &fieldname); type = parse_expression_for_completion (text, &fieldname, &code);
} }
if (except.reason < 0) if (except.reason < 0)
return NULL; return NULL;
@ -422,6 +423,15 @@ expression_completer (struct cmd_list_element *ignore,
return result; return result;
} }
} }
else if (fieldname && code != TYPE_CODE_UNDEF)
{
VEC (char_ptr) *result;
struct cleanup *cleanup = make_cleanup (xfree, fieldname);
result = make_symbol_completion_type (fieldname, fieldname, code);
do_cleanups (cleanup);
return result;
}
xfree (fieldname); xfree (fieldname);
/* Commands which complete on locations want to see the entire /* Commands which complete on locations want to see the entire

View File

@ -98,7 +98,8 @@ struct expression
extern struct expression *parse_expression (char *); extern struct expression *parse_expression (char *);
extern struct type *parse_expression_for_completion (char *, char **); extern struct type *parse_expression_for_completion (char *, char **,
enum type_code *);
extern struct expression *parse_exp_1 (char **, CORE_ADDR pc, extern struct expression *parse_exp_1 (char **, CORE_ADDR pc,
const struct block *, int); const struct block *, int);

View File

@ -230,9 +230,9 @@ f_word_break_characters (void)
class. */ class. */
static VEC (char_ptr) * static VEC (char_ptr) *
f_make_symbol_completion_list (char *text, char *word) f_make_symbol_completion_list (char *text, char *word, enum type_code code)
{ {
return default_make_symbol_completion_list_break_on (text, word, ":"); return default_make_symbol_completion_list_break_on (text, word, ":", code);
} }
const struct language_defn f_language_defn = const struct language_defn f_language_defn =

View File

@ -284,8 +284,11 @@ struct language_defn
/* Should return a vector of all symbols which are possible /* Should return a vector of all symbols which are possible
completions for TEXT. WORD is the entire command on which the completions for TEXT. WORD is the entire command on which the
completion is being made. */ completion is being made. If CODE is TYPE_CODE_UNDEF, then all
VEC (char_ptr) *(*la_make_symbol_completion_list) (char *text, char *word); symbols should be examined; otherwise, only STRUCT_DOMAIN
symbols whose type has a code of CODE should be matched. */
VEC (char_ptr) *(*la_make_symbol_completion_list) (char *text, char *word,
enum type_code code);
/* The per-architecture (OS/ABI) language information. */ /* The per-architecture (OS/ABI) language information. */
void (*la_language_arch_info) (struct gdbarch *, void (*la_language_arch_info) (struct gdbarch *,

View File

@ -88,6 +88,13 @@ int parse_completion;
'->'. This is set when parsing and is only used when completing a '->'. This is set when parsing and is only used when completing a
field name. It is -1 if no dereference operation was found. */ field name. It is -1 if no dereference operation was found. */
static int expout_last_struct = -1; static int expout_last_struct = -1;
/* If we are completing a tagged type name, this will be nonzero. */
static enum type_code expout_tag_completion_type = TYPE_CODE_UNDEF;
/* The token for tagged type name completion. */
static char *expout_completion_name;
static unsigned int expressiondebug = 0; static unsigned int expressiondebug = 0;
static void static void
@ -578,9 +585,32 @@ write_exp_msymbol (struct minimal_symbol *msymbol)
void void
mark_struct_expression (void) mark_struct_expression (void)
{ {
gdb_assert (parse_completion
&& expout_tag_completion_type == TYPE_CODE_UNDEF);
expout_last_struct = expout_ptr; expout_last_struct = expout_ptr;
} }
/* Indicate that the current parser invocation is completing a tag.
TAG is the type code of the tag, and PTR and LENGTH represent the
start of the tag name. */
void
mark_completion_tag (enum type_code tag, const char *ptr, int length)
{
gdb_assert (parse_completion
&& expout_tag_completion_type == TYPE_CODE_UNDEF
&& expout_completion_name == NULL
&& expout_last_struct == -1);
gdb_assert (tag == TYPE_CODE_UNION
|| tag == TYPE_CODE_STRUCT
|| tag == TYPE_CODE_CLASS
|| tag == TYPE_CODE_ENUM);
expout_tag_completion_type = tag;
expout_completion_name = xmalloc (length + 1);
memcpy (expout_completion_name, ptr, length);
expout_completion_name[length] = '\0';
}
/* Recognize tokens that start with '$'. These include: /* Recognize tokens that start with '$'. These include:
@ -1124,6 +1154,9 @@ parse_exp_in_context (char **stringptr, CORE_ADDR pc, const struct block *block,
paren_depth = 0; paren_depth = 0;
type_stack.depth = 0; type_stack.depth = 0;
expout_last_struct = -1; expout_last_struct = -1;
expout_tag_completion_type = TYPE_CODE_UNDEF;
xfree (expout_completion_name);
expout_completion_name = NULL;
comma_terminates = comma; comma_terminates = comma;
@ -1244,7 +1277,8 @@ parse_expression (char *string)
*NAME must be freed by the caller. */ *NAME must be freed by the caller. */
struct type * struct type *
parse_expression_for_completion (char *string, char **name) parse_expression_for_completion (char *string, char **name,
enum type_code *code)
{ {
struct expression *exp = NULL; struct expression *exp = NULL;
struct value *val; struct value *val;
@ -1259,6 +1293,15 @@ parse_expression_for_completion (char *string, char **name)
parse_completion = 0; parse_completion = 0;
if (except.reason < 0 || ! exp) if (except.reason < 0 || ! exp)
return NULL; return NULL;
if (expout_tag_completion_type != TYPE_CODE_UNDEF)
{
*code = expout_tag_completion_type;
*name = expout_completion_name;
expout_completion_name = NULL;
return NULL;
}
if (expout_last_struct == -1) if (expout_last_struct == -1)
{ {
xfree (exp); xfree (exp);

View File

@ -372,4 +372,8 @@ extern void parser_fprintf (FILE *, const char *, ...) ATTRIBUTE_PRINTF (2, 3);
extern int exp_uses_objfile (struct expression *exp, struct objfile *objfile); extern int exp_uses_objfile (struct expression *exp, struct objfile *objfile);
extern void mark_completion_tag (enum type_code, const char *ptr,
int length);
#endif /* PARSER_DEFS_H */ #endif /* PARSER_DEFS_H */

View File

@ -4202,7 +4202,8 @@ expand_partial_symbol_name (const char *name, void *user_data)
VEC (char_ptr) * VEC (char_ptr) *
default_make_symbol_completion_list_break_on (char *text, char *word, default_make_symbol_completion_list_break_on (char *text, char *word,
const char *break_on) const char *break_on,
enum type_code code)
{ {
/* Problem: All of the symbols have to be copied because readline /* Problem: All of the symbols have to be copied because readline
frees them. I'm not going to worry about this; hopefully there frees them. I'm not going to worry about this; hopefully there
@ -4309,13 +4310,18 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
anything that isn't a text symbol (everything else will be anything that isn't a text symbol (everything else will be
handled by the psymtab code above). */ handled by the psymtab code above). */
ALL_MSYMBOLS (objfile, msymbol) if (code == TYPE_CODE_UNDEF)
{ {
QUIT; ALL_MSYMBOLS (objfile, msymbol)
COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word); {
QUIT;
COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text,
word);
completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text, word); completion_list_objc_symbol (msymbol, sym_text, sym_text_len, text,
} word);
}
}
/* Search upwards from currently selected frame (so that we can /* Search upwards from currently selected frame (so that we can
complete on local vars). Also catch fields of types defined in complete on local vars). Also catch fields of types defined in
@ -4332,10 +4338,17 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
ALL_BLOCK_SYMBOLS (b, iter, sym) ALL_BLOCK_SYMBOLS (b, iter, sym)
{ {
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, if (code == TYPE_CODE_UNDEF)
word); {
completion_list_add_fields (sym, sym_text, sym_text_len, text, COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
word); word);
completion_list_add_fields (sym, sym_text, sym_text_len, text,
word);
}
else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code)
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
word);
} }
/* Stop when we encounter an enclosing function. Do not stop for /* Stop when we encounter an enclosing function. Do not stop for
@ -4348,13 +4361,16 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
/* Add fields from the file's types; symbols will be added below. */ /* Add fields from the file's types; symbols will be added below. */
if (surrounding_static_block != NULL) if (code == TYPE_CODE_UNDEF)
ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym) {
completion_list_add_fields (sym, sym_text, sym_text_len, text, word); if (surrounding_static_block != NULL)
ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
if (surrounding_global_block != NULL) if (surrounding_global_block != NULL)
ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym) ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
completion_list_add_fields (sym, sym_text, sym_text_len, text, word); completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
}
/* Go through the symtabs and check the externs and statics for /* Go through the symtabs and check the externs and statics for
symbols which match. */ symbols which match. */
@ -4365,7 +4381,10 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, sym) ALL_BLOCK_SYMBOLS (b, iter, sym)
{ {
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word); if (code == TYPE_CODE_UNDEF
|| (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code))
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
} }
} }
@ -4375,11 +4394,17 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
ALL_BLOCK_SYMBOLS (b, iter, sym) ALL_BLOCK_SYMBOLS (b, iter, sym)
{ {
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word); if (code == TYPE_CODE_UNDEF
|| (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
&& TYPE_CODE (SYMBOL_TYPE (sym)) == code))
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
} }
} }
if (current_language->la_macro_expansion == macro_expansion_c) /* Skip macros if we are completing a struct tag -- arguable but
usually what is expected. */
if (current_language->la_macro_expansion == macro_expansion_c
&& code == TYPE_CODE_UNDEF)
{ {
struct macro_scope *scope; struct macro_scope *scope;
@ -4407,9 +4432,10 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
} }
VEC (char_ptr) * VEC (char_ptr) *
default_make_symbol_completion_list (char *text, char *word) default_make_symbol_completion_list (char *text, char *word,
enum type_code code)
{ {
return default_make_symbol_completion_list_break_on (text, word, ""); return default_make_symbol_completion_list_break_on (text, word, "", code);
} }
/* Return a vector of all symbols (regardless of class) which begin by /* Return a vector of all symbols (regardless of class) which begin by
@ -4419,7 +4445,21 @@ default_make_symbol_completion_list (char *text, char *word)
VEC (char_ptr) * VEC (char_ptr) *
make_symbol_completion_list (char *text, char *word) make_symbol_completion_list (char *text, char *word)
{ {
return current_language->la_make_symbol_completion_list (text, word); return current_language->la_make_symbol_completion_list (text, word,
TYPE_CODE_UNDEF);
}
/* Like make_symbol_completion_list, but only return STRUCT_DOMAIN
symbols whose type code is CODE. */
VEC (char_ptr) *
make_symbol_completion_type (char *text, char *word, enum type_code code)
{
gdb_assert (code == TYPE_CODE_UNION
|| code == TYPE_CODE_STRUCT
|| code == TYPE_CODE_CLASS
|| code == TYPE_CODE_ENUM);
return current_language->la_make_symbol_completion_list (text, word, code);
} }
/* Like make_symbol_completion_list, but suitable for use as a /* Like make_symbol_completion_list, but suitable for use as a

View File

@ -23,6 +23,7 @@
#include "vec.h" #include "vec.h"
#include "gdb_vecs.h" #include "gdb_vecs.h"
#include "gdbtypes.h"
/* Opaque declarations. */ /* Opaque declarations. */
struct ui_file; struct ui_file;
@ -1182,9 +1183,13 @@ extern void forget_cached_source_info (void);
extern void select_source_symtab (struct symtab *); extern void select_source_symtab (struct symtab *);
extern VEC (char_ptr) *default_make_symbol_completion_list_break_on extern VEC (char_ptr) *default_make_symbol_completion_list_break_on
(char *text, char *word, const char *break_on); (char *text, char *word, const char *break_on,
extern VEC (char_ptr) *default_make_symbol_completion_list (char *, char *); enum type_code code);
extern VEC (char_ptr) *default_make_symbol_completion_list (char *, char *,
enum type_code);
extern VEC (char_ptr) *make_symbol_completion_list (char *, char *); extern VEC (char_ptr) *make_symbol_completion_list (char *, char *);
extern VEC (char_ptr) *make_symbol_completion_type (char *, char *,
enum type_code);
extern VEC (char_ptr) *make_symbol_completion_list_fn (struct cmd_list_element *, extern VEC (char_ptr) *make_symbol_completion_list_fn (struct cmd_list_element *,
char *, char *); char *, char *);

View File

@ -1,3 +1,9 @@
2012-12-07 Tom Tromey <tromey@redhat.com>
* gdb.base/break1.c (enum some_enum, union some_union): New.
(some_enum_global, some_union_global, some_value): New globals.
* gdb.base/completion.exp: Add tag completion tests.
2012-12-07 Tom Tromey <tromey@redhat.com> 2012-12-07 Tom Tromey <tromey@redhat.com>
* gdb.base/completion.exp: Add tests for ptype and whatis * gdb.base/completion.exp: Add tests for ptype and whatis

View File

@ -29,6 +29,23 @@ struct some_struct
struct some_struct values[50]; struct some_struct values[50];
/* Some definitions for tag completion. */
enum some_enum { VALUE };
enum some_enum some_enum_global;
union some_union
{
int f1;
double f2;
};
union some_union some_union_global;
/* A variable with a name "similar" to the above struct, to test that
tag completion works ok. */
int some_variable;
/* The following functions do nothing useful. They are included /* The following functions do nothing useful. They are included
simply as places to try setting breakpoints at. They are simply as places to try setting breakpoints at. They are
explicitly "one-line functions" to verify that this case works explicitly "one-line functions" to verify that this case works

View File

@ -700,6 +700,14 @@ gdb_test "complete sav" "save" "test non-deprecated completion"
gdb_test "complete save-t" "save-tracepoints" "test deprecated completion" gdb_test "complete save-t" "save-tracepoints" "test deprecated completion"
#
# Tag name completion.
#
gdb_test "complete ptype struct some_" "ptype struct some_struct"
gdb_test "complete ptype enum some_" "ptype enum some_enum"
gdb_test "complete ptype union some_" "ptype union some_union"
# Restore globals modified in this test... # Restore globals modified in this test...
set timeout $oldtimeout1 set timeout $oldtimeout1