* 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.
This commit is contained in:
parent
11ef0d76ab
commit
1290797801
@ -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
|
||||
|
116
gdb/cp-support.c
116
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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user