X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fcp-support.c;h=684943bcc25bd08b1bf90440b9a7ec90e683ea44;hb=1290797801825ff96506c8197d301b60154c3250;hp=3c5cd0755f8f315f12f7ecb22239093f8645f705;hpb=5e5100cb9c0c310eb1c4378441c24b3a95d3c46d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 3c5cd0755f..684943bcc2 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -1,5 +1,6 @@ /* Helper routines for C++ support in GDB. - Copyright 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009 + 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., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, 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,11 @@ #include "block.h" #include "complaints.h" #include "gdbtypes.h" +#include "exceptions.h" +#include "expression.h" +#include "value.h" + +#include "safe-ctype.h" #define d_left(dc) (dc)->u.s_binary.left #define d_right(dc) (dc)->u.s_binary.right @@ -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; } @@ -130,11 +178,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 +195,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,7 +339,7 @@ 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; @@ -323,12 +371,11 @@ 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 +385,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 +392,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 +428,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 +557,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 +664,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; @@ -687,10 +731,10 @@ 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); } } @@ -750,7 +794,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 +808,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); @@ -812,7 +856,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 +907,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 +924,107 @@ 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; + struct cleanup *old_chain; + + 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) {