X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fcp-support.c;h=e4b5d4d7b5dd551e475bda577e9846c4552427cb;hb=d0ef7741c534042736e2f2734daceb4738715f80;hp=ba4e891e19c9eab1c36548d3e536cd2aa4bd62c6;hpb=01f0fe5e0450edf168c1f612feb93cf588e4e7ea;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index ba4e891e19..e4b5d4d7b5 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1,5 +1,6 @@
/* Helper routines for C++ support in GDB.
- Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
Contributed by MontaVista Software.
@@ -7,7 +8,7 @@
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -16,12 +17,9 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see . */
#include "defs.h"
-#include
#include "cp-support.h"
#include "gdb_string.h"
#include "demangle.h"
@@ -34,6 +32,13 @@
#include "block.h"
#include "complaints.h"
#include "gdbtypes.h"
+#include "exceptions.h"
+#include "expression.h"
+#include "value.h"
+
+#include "safe-ctype.h"
+
+#include "psymtab.h"
#define d_left(dc) (dc)->u.s_binary.left
#define d_right(dc) (dc)->u.s_binary.right
@@ -47,7 +52,7 @@ static void demangled_name_complaint (const char *name);
/* Functions/variables related to overload resolution. */
-static int sym_return_val_size;
+static int sym_return_val_size = -1;
static int sym_return_val_index;
static struct symbol **sym_return_val;
@@ -59,8 +64,6 @@ static void make_symbol_overload_list_using (const char *func_name,
static void make_symbol_overload_list_qualified (const char *func_name);
-static void read_in_psymtabs (const char *oload_name);
-
/* The list of "maint cplus" commands. */
struct cmd_list_element *maint_cplus_cmd_list = NULL;
@@ -70,30 +73,75 @@ struct cmd_list_element *maint_cplus_cmd_list = NULL;
static void maint_cplus_command (char *arg, int from_tty);
static void first_component_command (char *arg, int from_tty);
-/* Return the canonicalized form of STRING, or NULL if STRING can not be
- parsed. The return value is allocated via xmalloc.
+/* Operator validation.
+ NOTE: Multi-byte operators (usually the assignment variety operator)
+ must appear before the single byte version, i.e., "+=" before "+". */
+static const char *operator_tokens[] =
+ {
+ "++", "+=", "+", "->*", "->", "--", "-=", "-", "*=", "*", "/=", "/",
+ "%=", "%", "!=", "==", "!", "&&", "<<=", "<<", ">>=", ">>",
+ "<=", "<", ">=", ">", "~", "&=", "&", "|=", "||", "|", "^=", "^",
+ "=", "()", "[]", ",", "new", "delete"
+ /* new[] and delete[] require special whitespace handling */
+ };
+
+/* Return 1 if STRING is clearly already in canonical form. This
+ function is conservative; things which it does not recognize are
+ assumed to be non-canonical, and the parser will sort them out
+ afterwards. This speeds up the critical path for alphanumeric
+ identifiers. */
+
+static int
+cp_already_canonical (const char *string)
+{
+ /* Identifier start character [a-zA-Z_]. */
+ if (!ISIDST (string[0]))
+ return 0;
+
+ /* These are the only two identifiers which canonicalize to other
+ than themselves or an error: unsigned -> unsigned int and
+ signed -> int. */
+ if (string[0] == 'u' && strcmp (&string[1], "nsigned") == 0)
+ return 0;
+ else if (string[0] == 's' && strcmp (&string[1], "igned") == 0)
+ return 0;
+
+ /* Identifier character [a-zA-Z0-9_]. */
+ while (ISIDNUM (string[1]))
+ string++;
+
+ if (string[1] == '\0')
+ return 1;
+ else
+ return 0;
+}
- drow/2005-03-07: Should we also return NULL for things that trivially do
- not require any change? e.g. simple identifiers. This could be more
- efficient. */
+/* Parse STRING and convert it to canonical form. If parsing fails,
+ or if STRING is already canonical, return NULL. Otherwise return
+ the canonical form. The return value is allocated via xmalloc. */
char *
cp_canonicalize_string (const char *string)
{
- void *storage;
struct demangle_component *ret_comp;
+ unsigned int estimated_len;
char *ret;
- int len = strlen (string);
- len = len + len / 8;
+ if (cp_already_canonical (string))
+ return NULL;
- ret_comp = cp_demangled_name_to_comp (string, &storage, NULL);
+ ret_comp = cp_demangled_name_to_comp (string, NULL);
if (ret_comp == NULL)
return NULL;
- ret = cp_comp_to_string (ret_comp, len);
+ estimated_len = strlen (string) * 2;
+ ret = cp_comp_to_string (ret_comp, estimated_len);
- xfree (storage);
+ if (strcmp (string, ret) == 0)
+ {
+ xfree (ret);
+ return NULL;
+ }
return ret;
}
@@ -110,7 +158,6 @@ mangled_name_to_comp (const char *mangled_name, int options,
{
struct demangle_component *ret;
char *demangled_name;
- int len;
/* If it looks like a v3 mangled name, then try to go directly
to trees. */
@@ -130,11 +177,11 @@ mangled_name_to_comp (const char *mangled_name, int options,
return NULL;
/* If we could demangle the name, parse it to build the component tree. */
- ret = cp_demangled_name_to_comp (demangled_name, memory, NULL);
+ ret = cp_demangled_name_to_comp (demangled_name, NULL);
if (ret == NULL)
{
- free (demangled_name);
+ xfree (demangled_name);
return NULL;
}
@@ -147,7 +194,7 @@ mangled_name_to_comp (const char *mangled_name, int options,
char *
cp_class_name_from_physname (const char *physname)
{
- void *storage;
+ void *storage = NULL;
char *demangled_name = NULL, *ret;
struct demangle_component *ret_comp, *prev_comp, *cur_comp;
int done;
@@ -291,10 +338,9 @@ unqualified_name_from_comp (struct demangle_component *comp)
char *
method_name_from_physname (const char *physname)
{
- void *storage;
+ void *storage = NULL;
char *demangled_name = NULL, *ret;
struct demangle_component *ret_comp;
- int done;
ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &storage,
&demangled_name);
@@ -323,12 +369,10 @@ method_name_from_physname (const char *physname)
char *
cp_func_name (const char *full_name)
{
- void *storage;
char *ret;
struct demangle_component *ret_comp;
- int done;
- ret_comp = cp_demangled_name_to_comp (full_name, &storage, NULL);
+ ret_comp = cp_demangled_name_to_comp (full_name, NULL);
if (!ret_comp)
return NULL;
@@ -338,7 +382,6 @@ cp_func_name (const char *full_name)
if (ret_comp != NULL)
ret = cp_comp_to_string (ret_comp, 10);
- xfree (storage);
return ret;
}
@@ -346,18 +389,17 @@ cp_func_name (const char *full_name)
(optionally) a return type. Return the name of the function without
parameters or return type, or NULL if we can not parse the name. */
-static char *
-remove_params (const char *demangled_name)
+char *
+cp_remove_params (const char *demangled_name)
{
int done = 0;
struct demangle_component *ret_comp;
- void *storage;
char *ret = NULL;
if (demangled_name == NULL)
return NULL;
- ret_comp = cp_demangled_name_to_comp (demangled_name, &storage, NULL);
+ ret_comp = cp_demangled_name_to_comp (demangled_name, NULL);
if (ret_comp == NULL)
return NULL;
@@ -383,7 +425,6 @@ remove_params (const char *demangled_name)
if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
ret = cp_comp_to_string (d_left (ret_comp), 10);
- xfree (storage);
return ret;
}
@@ -513,7 +554,7 @@ cp_find_first_component_aux (const char *name, int permissive)
&& strncmp (name + index, "operator", LENGTH_OF_OPERATOR) == 0)
{
index += LENGTH_OF_OPERATOR;
- while (isspace(name[index]))
+ while (ISSPACE(name[index]))
++index;
switch (name[index])
{
@@ -620,7 +661,7 @@ overload_list_add_symbol (struct symbol *sym, const char *oload_name)
return;
/* Get the demangled name without parameters */
- sym_name = remove_params (SYMBOL_NATURAL_NAME (sym));
+ sym_name = cp_remove_params (SYMBOL_NATURAL_NAME (sym));
if (!sym_name)
return;
@@ -668,6 +709,87 @@ make_symbol_overload_list (const char *func_name,
return sym_return_val;
}
+/* Adds the function FUNC_NAME from NAMESPACE to the overload set. */
+
+static void
+make_symbol_overload_list_namespace (const char *func_name,
+ const char *namespace)
+{
+ if (namespace[0] == '\0')
+ make_symbol_overload_list_qualified (func_name);
+ else
+ {
+ char *concatenated_name
+ = alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
+
+ strcpy (concatenated_name, namespace);
+ strcat (concatenated_name, "::");
+ strcat (concatenated_name, func_name);
+ make_symbol_overload_list_qualified (concatenated_name);
+ }
+}
+
+/* Search the namespace of the given type and namespace of and public base
+ types. */
+
+static void
+make_symbol_overload_list_adl_namespace (struct type *type,
+ const char *func_name)
+{
+ char *namespace;
+ char *type_name;
+ int i, prefix_len;
+
+ while (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY
+ || TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+ {
+ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+ type = check_typedef(type);
+ else
+ type = TYPE_TARGET_TYPE (type);
+ }
+
+ type_name = TYPE_NAME (type);
+
+ prefix_len = cp_entire_prefix_len (type_name);
+
+ if (prefix_len != 0)
+ {
+ namespace = alloca (prefix_len + 1);
+ strncpy (namespace, type_name, prefix_len);
+ namespace[prefix_len] = '\0';
+
+ make_symbol_overload_list_namespace (func_name, namespace);
+ }
+
+ /* Check public base type */
+ if (TYPE_CODE (type) == TYPE_CODE_CLASS)
+ for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
+ {
+ if (BASETYPE_VIA_PUBLIC (type, i))
+ make_symbol_overload_list_adl_namespace (TYPE_BASECLASS (type, i),
+ func_name);
+ }
+}
+
+/* Adds the the overload list overload candidates for FUNC_NAME found through
+ argument dependent lookup. */
+
+struct symbol **
+make_symbol_overload_list_adl (struct type **arg_types, int nargs,
+ const char *func_name)
+{
+ int i;
+
+ gdb_assert (sym_return_val_size != -1);
+
+ for (i = 1; i <= nargs; i++)
+ make_symbol_overload_list_adl_namespace (arg_types[i - 1], func_name);
+
+ return sym_return_val;
+}
+
/* This applies the using directives to add namespaces to search in,
and then searches for overloads in all of those namespaces. It
adds the symbols found to sym_return_val. Arguments are as in
@@ -687,28 +809,15 @@ make_symbol_overload_list_using (const char *func_name,
current != NULL;
current = current->next)
{
- if (strcmp (namespace, current->outer) == 0)
+ if (strcmp (namespace, current->import_dest) == 0)
{
make_symbol_overload_list_using (func_name,
- current->inner);
+ current->import_src);
}
}
/* Now, add names for this namespace. */
-
- if (namespace[0] == '\0')
- {
- make_symbol_overload_list_qualified (func_name);
- }
- else
- {
- char *concatenated_name
- = alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
- strcpy (concatenated_name, namespace);
- strcat (concatenated_name, "::");
- strcat (concatenated_name, func_name);
- make_symbol_overload_list_qualified (concatenated_name);
- }
+ make_symbol_overload_list_namespace (func_name, namespace);
}
/* This does the bulk of the work of finding overloaded symbols.
@@ -728,7 +837,11 @@ make_symbol_overload_list_qualified (const char *func_name)
/* Look through the partial symtabs for all symbols which begin
by matching FUNC_NAME. Make sure we read that symbol table in. */
- read_in_psymtabs (func_name);
+ ALL_OBJFILES (objfile)
+ {
+ if (objfile->sf)
+ objfile->sf->qf->expand_symtabs_for_function (objfile, func_name);
+ }
/* Search upwards from currently selected frame (so that we can
complete on local vars. */
@@ -750,7 +863,7 @@ make_symbol_overload_list_qualified (const char *func_name)
/* Go through the symtabs and check the externs and statics for
symbols which match. */
- ALL_SYMTABS (objfile, s)
+ ALL_PRIMARY_SYMTABS (objfile, s)
{
QUIT;
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
@@ -764,7 +877,7 @@ make_symbol_overload_list_qualified (const char *func_name)
}
}
- ALL_SYMTABS (objfile, s)
+ ALL_PRIMARY_SYMTABS (objfile, s)
{
QUIT;
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
@@ -782,28 +895,6 @@ make_symbol_overload_list_qualified (const char *func_name)
}
}
-/* Look through the partial symtabs for all symbols which begin
- by matching FUNC_NAME. Make sure we read that symbol table in. */
-
-static void
-read_in_psymtabs (const char *func_name)
-{
- struct partial_symtab *ps;
- struct objfile *objfile;
-
- ALL_PSYMTABS (objfile, ps)
- {
- if (ps->readin)
- continue;
-
- if ((lookup_partial_symbol (ps, func_name, NULL, 1, VAR_DOMAIN)
- != NULL)
- || (lookup_partial_symbol (ps, func_name, NULL, 0, VAR_DOMAIN)
- != NULL))
- psymtab_to_symtab (ps);
- }
-}
-
/* Lookup the rtti type for a class name. */
struct type *
@@ -812,7 +903,7 @@ cp_lookup_rtti_type (const char *name, struct block *block)
struct symbol * rtti_sym;
struct type * rtti_type;
- rtti_sym = lookup_symbol (name, block, STRUCT_DOMAIN, NULL, NULL);
+ rtti_sym = lookup_symbol (name, block, STRUCT_DOMAIN, NULL);
if (rtti_sym == NULL)
{
@@ -863,8 +954,14 @@ maint_cplus_command (char *arg, int from_tty)
static void
first_component_command (char *arg, int from_tty)
{
- int len = cp_find_first_component (arg);
- char *prefix = alloca (len + 1);
+ int len;
+ char *prefix;
+
+ if (!arg)
+ return;
+
+ len = cp_find_first_component (arg);
+ prefix = alloca (len + 1);
memcpy (prefix, arg, len);
prefix[len] = '\0';
@@ -874,6 +971,108 @@ first_component_command (char *arg, int from_tty)
extern initialize_file_ftype _initialize_cp_support; /* -Wmissing-prototypes */
+#define SKIP_SPACE(P) \
+ do \
+ { \
+ while (*(P) == ' ' || *(P) == '\t') \
+ ++(P); \
+ } \
+ while (0)
+
+/* Returns the length of the operator name or 0 if INPUT does not
+ point to a valid C++ operator. INPUT should start with "operator". */
+int
+cp_validate_operator (const char *input)
+{
+ int i;
+ char *copy;
+ const char *p;
+ struct expression *expr;
+ struct value *val;
+ struct gdb_exception except;
+
+ p = input;
+
+ if (strncmp (p, "operator", 8) == 0)
+ {
+ int valid = 0;
+
+ p += 8;
+ SKIP_SPACE (p);
+ for (i = 0; i < sizeof (operator_tokens) / sizeof (operator_tokens[0]);
+ ++i)
+ {
+ int length = strlen (operator_tokens[i]);
+
+ /* By using strncmp here, we MUST have operator_tokens ordered!
+ See additional notes where operator_tokens is defined above. */
+ if (strncmp (p, operator_tokens[i], length) == 0)
+ {
+ const char *op = p;
+
+ valid = 1;
+ p += length;
+
+ if (strncmp (op, "new", 3) == 0
+ || strncmp (op, "delete", 6) == 0)
+ {
+
+ /* Special case: new[] and delete[]. We must be careful
+ to swallow whitespace before/in "[]". */
+ SKIP_SPACE (p);
+
+ if (*p == '[')
+ {
+ ++p;
+ SKIP_SPACE (p);
+ if (*p == ']')
+ ++p;
+ else
+ valid = 0;
+ }
+ }
+
+ if (valid)
+ return (p - input);
+ }
+ }
+
+ /* Check input for a conversion operator. */
+
+ /* Skip past base typename */
+ while (*p != '*' && *p != '&' && *p != 0 && *p != ' ')
+ ++p;
+ SKIP_SPACE (p);
+
+ /* Add modifiers '*'/'&' */
+ while (*p == '*' || *p == '&')
+ {
+ ++p;
+ SKIP_SPACE (p);
+ }
+
+ /* Check for valid type. [Remember: input starts with
+ "operator".] */
+ copy = savestring (input + 8, p - input - 8);
+ expr = NULL;
+ val = NULL;
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ expr = parse_expression (copy);
+ val = evaluate_type (expr);
+ }
+
+ xfree (copy);
+ if (expr)
+ xfree (expr);
+
+ if (val != NULL && value_type (val) != NULL)
+ return (p - input);
+ }
+
+ return 0;
+}
+
void
_initialize_cp_support (void)
{