aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog28
-rw-r--r--gdb/ada-lang.c4
-rw-r--r--gdb/c-exp.y44
-rw-r--r--gdb/completer.c12
-rw-r--r--gdb/expression.h3
-rw-r--r--gdb/f-lang.c4
-rw-r--r--gdb/language.h7
-rw-r--r--gdb/parse.c45
-rw-r--r--gdb/parser-defs.h4
-rw-r--r--gdb/symtab.c86
-rw-r--r--gdb/symtab.h9
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.base/break1.c17
-rw-r--r--gdb/testsuite/gdb.base/completion.exp8
14 files changed, 244 insertions, 33 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index cc066c1..37f2bfb 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,33 @@
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
from parse_field_expression.
(parse_completion): Rename from in_parse_field.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index b03b2a2..f07e4bc 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -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);
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 7ae90aa..dc89c3e 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -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,
diff --git a/gdb/completer.c b/gdb/completer.c
index 7954c2c..946717d 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -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
diff --git a/gdb/expression.h b/gdb/expression.h
index a667845..1a2b62a 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -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);
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 0b3645f..344d9b8 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -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 =
diff --git a/gdb/language.h b/gdb/language.h
index 3a1e390..49afbc4 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -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 *,
diff --git a/gdb/parse.c b/gdb/parse.c
index 984c0d2..8e558e3 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -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);
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index 6dd5329..a6f1983 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -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 */
+
diff --git a/gdb/symtab.c b/gdb/symtab.c
index dee47a9..cf32a8c 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -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
diff --git a/gdb/symtab.h b/gdb/symtab.h
index d1cbef5..a933132 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -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 *);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 0bdd094..6e3731e 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,11 @@
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
completion.
diff --git a/gdb/testsuite/gdb.base/break1.c b/gdb/testsuite/gdb.base/break1.c
index af4f2b0..1f0654e 100644
--- a/gdb/testsuite/gdb.base/break1.c
+++ b/gdb/testsuite/gdb.base/break1.c
@@ -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
diff --git a/gdb/testsuite/gdb.base/completion.exp b/gdb/testsuite/gdb.base/completion.exp
index c8edc98..006670d 100644
--- a/gdb/testsuite/gdb.base/completion.exp
+++ b/gdb/testsuite/gdb.base/completion.exp
@@ -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