aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/cp-support.c116
-rw-r--r--gdb/cp-support.h2
-rw-r--r--gdb/linespec.c27
4 files changed, 139 insertions, 12 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f9a865e..63f0ca4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2009-09-18 Keith Seitz <keiths@redhat.com>
+
+ * cp-support.h (cp_validate_operator): Declare new function.
+ * cp-support.c (cp_validate_operator): New function.
+ * linespec.c (decode_compound): For C++ check for a valid operator.
+
2009-09-21 Keith Seitz <keiths@redhat.com>
* c-exp.y (qualified_name): Call CHECK_TYPEDEF before deciding
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index f12d785..684943b 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -32,6 +32,9 @@
#include "block.h"
#include "complaints.h"
#include "gdbtypes.h"
+#include "exceptions.h"
+#include "expression.h"
+#include "value.h"
#include "safe-ctype.h"
@@ -70,6 +73,18 @@ 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);
+/* 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
@@ -909,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)
{
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index b5a5c5f..7ecd201 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -72,6 +72,8 @@ extern struct symbol **make_symbol_overload_list (const char *,
extern struct type *cp_lookup_rtti_type (const char *name,
struct block *block);
+extern int cp_validate_operator (const char *input);
+
/* Functions/variables from cp-namespace.c. */
extern int cp_is_anonymous (const char *namespace);
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 3e943a1..70e27f76 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -30,6 +30,7 @@
#include "value.h"
#include "completer.h"
#include "cp-abi.h"
+#include "cp-support.h"
#include "parser-defs.h"
#include "block.h"
#include "objc-lang.h"
@@ -1257,6 +1258,9 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
/* Move pointer ahead to next double-colon. */
while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
{
+ if (current_language->la_language == language_cplus)
+ p += cp_validate_operator (p);
+
if (p[0] == '<')
{
temp_end = find_template_name_end (p);
@@ -1334,6 +1338,15 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
p++;
/* At this point p->"". String ended. */
+ /* Nope, C++ operators could have spaces in them
+ ("foo::operator <" or "foo::operator delete []").
+ I apologize, this is a bit hacky... */
+ if (current_language->la_language == language_cplus
+ && *p == ' ' && p - 8 - *argptr + 1 > 0)
+ {
+ /* The above loop has already swallowed "operator". */
+ p += cp_validate_operator (p - 8) - 8;
+ }
}
/* Allocate our own copy of the substring between argptr and
@@ -1474,26 +1487,16 @@ find_method (int funfirstline, char ***canonical, char *saved_arg,
}
else
{
- char *tmp;
-
- if (is_operator_name (copy))
- {
- tmp = (char *) alloca (strlen (copy + 3) + 9);
- strcpy (tmp, "operator ");
- strcat (tmp, copy + 3);
- }
- else
- tmp = copy;
if (not_found_ptr)
*not_found_ptr = 1;
- if (tmp[0] == '~')
+ if (copy[0] == '~')
cplusplus_error (saved_arg,
"the class `%s' does not have destructor defined\n",
SYMBOL_PRINT_NAME (sym_class));
else
cplusplus_error (saved_arg,
"the class %s does not have any method named %s\n",
- SYMBOL_PRINT_NAME (sym_class), tmp);
+ SYMBOL_PRINT_NAME (sym_class), copy);
}
}