* 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>
* 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. */
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;
int text_len;
@ -5817,6 +5817,8 @@ ada_make_symbol_completion_list (char *text0, char *word)
int i;
struct block_iterator iter;
gdb_assert (code == TYPE_CODE_UNDEF);
if (text0[0] == '<')
{
text = xstrdup (text0);

View file

@ -1268,15 +1268,59 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */
| STRUCT name
{ $$ = lookup_struct (copy_name ($2),
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
{ $$ = lookup_struct (copy_name ($2),
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
{ $$ = lookup_union (copy_name ($2),
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
{ $$ = lookup_enum (copy_name ($2),
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
{ $$ = lookup_unsigned_typename (parse_language,
parse_gdbarch,

View file

@ -390,13 +390,14 @@ expression_completer (struct cmd_list_element *ignore,
struct type *type = NULL;
char *fieldname, *p;
volatile struct gdb_exception except;
enum type_code code = TYPE_CODE_UNDEF;
/* Perform a tentative parse of the expression, to see whether a
field completion is required. */
fieldname = NULL;
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)
return NULL;
@ -422,6 +423,15 @@ expression_completer (struct cmd_list_element *ignore,
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);
/* 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 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,
const struct block *, int);

View file

@ -230,9 +230,9 @@ f_word_break_characters (void)
class. */
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 =

View file

@ -284,8 +284,11 @@ struct language_defn
/* Should return a vector of all symbols which are possible
completions for TEXT. WORD is the entire command on which the
completion is being made. */
VEC (char_ptr) *(*la_make_symbol_completion_list) (char *text, char *word);
completion is being made. If CODE is TYPE_CODE_UNDEF, then all
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. */
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
field name. It is -1 if no dereference operation was found. */
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 void
@ -578,9 +585,32 @@ write_exp_msymbol (struct minimal_symbol *msymbol)
void
mark_struct_expression (void)
{
gdb_assert (parse_completion
&& expout_tag_completion_type == TYPE_CODE_UNDEF);
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:
@ -1124,6 +1154,9 @@ parse_exp_in_context (char **stringptr, CORE_ADDR pc, const struct block *block,
paren_depth = 0;
type_stack.depth = 0;
expout_last_struct = -1;
expout_tag_completion_type = TYPE_CODE_UNDEF;
xfree (expout_completion_name);
expout_completion_name = NULL;
comma_terminates = comma;
@ -1244,7 +1277,8 @@ parse_expression (char *string)
*NAME must be freed by the caller. */
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 value *val;
@ -1259,6 +1293,15 @@ parse_expression_for_completion (char *string, char **name)
parse_completion = 0;
if (except.reason < 0 || ! exp)
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)
{
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 void mark_completion_tag (enum type_code, const char *ptr,
int length);
#endif /* PARSER_DEFS_H */

View file

@ -4202,7 +4202,8 @@ expand_partial_symbol_name (const char *name, void *user_data)
VEC (char_ptr) *
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
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
handled by the psymtab code above). */
ALL_MSYMBOLS (objfile, msymbol)
{
QUIT;
COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word);
if (code == TYPE_CODE_UNDEF)
{
ALL_MSYMBOLS (objfile, msymbol)
{
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
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)
{
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
word);
completion_list_add_fields (sym, sym_text, sym_text_len, text,
word);
if (code == TYPE_CODE_UNDEF)
{
COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text,
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
@ -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. */
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 (code == TYPE_CODE_UNDEF)
{
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)
ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
if (surrounding_global_block != NULL)
ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
completion_list_add_fields (sym, sym_text, sym_text_len, text, word);
}
/* Go through the symtabs and check the externs and statics for
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);
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);
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;
@ -4407,9 +4432,10 @@ default_make_symbol_completion_list_break_on (char *text, char *word,
}
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
@ -4419,7 +4445,21 @@ default_make_symbol_completion_list (char *text, char *word)
VEC (char_ptr) *
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

View file

@ -23,6 +23,7 @@
#include "vec.h"
#include "gdb_vecs.h"
#include "gdbtypes.h"
/* Opaque declarations. */
struct ui_file;
@ -1182,9 +1183,13 @@ extern void forget_cached_source_info (void);
extern void select_source_symtab (struct symtab *);
extern VEC (char_ptr) *default_make_symbol_completion_list_break_on
(char *text, char *word, const char *break_on);
extern VEC (char_ptr) *default_make_symbol_completion_list (char *, char *);
(char *text, char *word, const char *break_on,
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_type (char *, char *,
enum type_code);
extern VEC (char_ptr) *make_symbol_completion_list_fn (struct cmd_list_element *,
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>
* gdb.base/completion.exp: Add tests for ptype and whatis

View file

@ -29,6 +29,23 @@ struct some_struct
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
simply as places to try setting breakpoints at. They are
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"
#
# 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...
set timeout $oldtimeout1