* 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:
Keith Seitz 2009-09-21 19:46:43 +00:00
parent 11ef0d76ab
commit 1290797801
4 changed files with 139 additions and 12 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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);

View File

@ -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);
}
}