New scope checking patch

Rob Quill
2007-11-12T16:29:35Z

[-- Attachment #1: Type: text/plain, Size: 2872 bytes --]

Hi all,

The attached patch adds the ability to evaluate whether expressions
are in scope without giving an error message. For example, if you were
using a command file to control GDB then it it may not be ideal that
the script stop executing due to a variable not being in scope at
given position.

This patch allows you to say (for example)

while(the program is not finished)
{
if($in_scope(x)) print x;
step;
}

which would step through he whole program and print all the values of
x where x is valid, and just continue stepping where it is not valid.

The bulk of the patch is changes to the evaluate_subexp functions in eval.c

The following cases are cases which the core is written for, but have
not been tested yet:

case OP_SCOPE:
case OP_REGISTER:
case OP_STRING:
case OP_OBJC_NSSTRING: /* Objective C Foundation
case OP_BITSTRING:
case UNOP_MEMVAL:
case UNOP_MEMVAL_TLS:
case OP_OBJC_SELF

These cases have not been tested as I am unsure of code or commands
which would allow me to test them. If anyone has any suggestions then
that is greatly appreciated.

The following cases are unimplemented as I am unsure of how to check
the scope of these expressions. Any advice you have is greatly
appreciated.

case OP_ARRAY:
case TERNOP_SLICE:
case TERNOP_SLICE_COUNT:
case TERNOP_COND:
case OP_OBJC_SELECTOR:
case OP_OBJC_MSGCALL:
case OP_FUNCALL:
case OP_F77_UNDETERMINED_ARGLIST:
case STRUCTOP_PTR:
case STRUCTOP_MEMBER:
case STRUCTOP_MPTR:
// case TYPE_CODE_METHODPTR:
// case TYPE_CODE_MEMBERPTR:
case MULTI_SUBSCRIPT:
case UNOP_IND:

For example, I think for a function call the way to check scope should
be to check that there is a function in scope with that name, and that
all the parameters are in scope. However, I am unsure how to implement
this.

TYPE_CODE_METHODPTR and TYPE_CODE_MEMBERPTR are commented out as they
are supposedly redefinitions of two other cases (greater than and less
than operators, I believe)

I should also point out that expression are evaluated without side
effects, so that, for example $in_scope(a = b) will return 1 if a and
b are in scope, but will not change the value of a.

There is a caveat with the patch which is as follows. If a variable is
not in scope then the expression parser in c-exp.y inserts a value 0
into the expression tree. When the scope checking function sees a 0
expression in the tree it will return 0, to indicate not in scope.
However, in the general case it should be true that all literals are
in scope. However, due to the above caveat $in_scope(0) will return 0,
any any other literal will return 1.

This also affects compound expressions that involve the literal 0. For
example, $in_scope(0+3) will return 0, as an expression with a binary
operator is considering in scope iff both of its operands are in
scope.

Any thoughts on the patch are greatly appreciated.

Thanks.

Rob Quill

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: new_scope_check.patch --]
[-- Type: text/x-patch; name=new_scope_check.patch, Size: 18345 bytes --]

diff -urN ./clean/src/gdb/29k-share/CVS/Entries ./modified/src/gdb/29k-share/CVS/Entries
--- ./clean/src/gdb/29k-share/CVS/Entries 2007-11-11 17:08:33.000000000 +0000
+++ ./modified/src/gdb/29k-share/CVS/Entries 2007-11-11 16:27:06.000000000 +0000
@@ -1 +1 @@
-D/udi////
+D
diff -urN ./clean/src/gdb/29k-share/CVS/Entries.Log ./modified/src/gdb/29k-share/CVS/Entries.Log
--- ./clean/src/gdb/29k-share/CVS/Entries.Log 1970-01-01 01:00:00.000000000 +0100
+++ ./modified/src/gdb/29k-share/CVS/Entries.Log 2007-11-11 16:27:06.000000000 +0000
@@ -0,0 +1 @@
+A D/udi////
diff -urN ./clean/src/gdb/c-exp.y ./modified/src/gdb/c-exp.y
--- ./clean/src/gdb/c-exp.y 2007-11-11 17:08:42.000000000 +0000
+++ ./modified/src/gdb/c-exp.y 2007-11-11 17:05:35.000000000 +0000
@@ -102,6 +102,9 @@
#define yytable c_yytable
#define yycheck c_yycheck

+/* Global variable denoting whether we are only interested in scope, not value */
+int check_scope = 0;
+
#ifndef YYDEBUG
#define YYDEBUG 1 /* Default to yydebug support */
#endif
@@ -207,6 +210,8 @@
%token TRUEKEYWORD
%token FALSEKEYWORD

+/* $in_scope opperator */
+%left IN_SCOPE

%left ','
%left ABOVE_COMMA
@@ -250,6 +255,11 @@
;

/* Expressions, not including the comma operator. */
+exp : IN_SCOPE
+ { check_scope = 1; }
+ '(' exp ')'
+ ;
+
exp : '*' exp %prec UNARY
{ write_exp_elt_opcode (UNOP_IND); }
;
@@ -596,8 +606,25 @@
VAR_DOMAIN, (int *) NULL,
(struct symtab **) NULL);
if (sym == 0)
- error ("No symbol \"%s\" in specified context.",
+ {
+ /* Case for scope checking. If scope is being checked and
+ the symbol is not in scope, return an expresison of
+ value 0. */
+ if(check_scope == 0)
+ {
+ error ("No symbol \"%s\" in specified context.",
copy_name ($3));
+ }
+ else
+ {
+ YYSTYPE val;
+ parse_number ("0", 1, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (val.typed_val_int.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ }

write_exp_elt_opcode (OP_VAR_VALUE);
/* block_found is set by lookup_symbol. */
@@ -676,8 +703,22 @@
if (!have_full_symbols () && !have_partial_symbols ())
error ("No symbol table is loaded. Use the \"file\" command.");
else
- error ("No symbol \"%s\" in current context.", name);
- }
+ {
+ if(check_scope == 0)
+ {
+ error ("No symbol \"%s\" in current context.", name);
+ }
+ else
+ {
+ YYSTYPE val;
+ parse_number ("0", 1, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (val.typed_val_int.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ }
+}
;

variable: name_not_typename
@@ -731,8 +772,19 @@
else if (!have_full_symbols () && !have_partial_symbols ())
error ("No symbol table is loaded. Use the \"file\" command.");
else
- error ("No symbol \"%s\" in current context.",
- copy_name ($1.stoken));
+ {
+ if(check_scope == 0)
+ error ("No symbol \"%s\" in current context.", copy_name ($1.stoken));
+ else
+ {
+ YYSTYPE val;
+ parse_number ("0", 1, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (val.typed_val_int.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ }
}
}
;
@@ -1310,6 +1362,11 @@
enum exp_opcode opcode;
};

+static const struct token tokentab9[] =
+ {
+ {"$in_scope", IN_SCOPE, BINOP_END}
+ };
+
static const struct token tokentab3[] =
{
{">>=", ASSIGN_MODIFY, BINOP_RSH},
@@ -1372,6 +1429,15 @@
prev_lexptr = lexptr;

tokstart = lexptr;
+ /* Code for recognising the $in_scope token. */
+ /* See if it is a special token of length 9. */
+ for (i = 0; i < sizeof tokentab9 / sizeof tokentab9[0]; i++)
+ if (strncmp (tokstart, tokentab9[i].operator, 9) == 0)
+ {
+ lexptr += 9;
+ yylval.opcode = tokentab9[i].opcode;
+ return tokentab9[i].token;
+ }
/* See if it is a special token of length 3. */
for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
if (strncmp (tokstart, tokentab3[i].operator, 3) == 0)
diff -urN ./clean/src/gdb/eval.c ./modified/src/gdb/eval.c
--- ./clean/src/gdb/eval.c 2007-11-11 17:08:42.000000000 +0000
+++ ./modified/src/gdb/eval.c 2007-11-12 15:54:37.000000000 +0000
@@ -44,11 +44,15 @@
/* This is defined in valops.c */
extern int overload_resolution;

+/* Variable denoting is scope is being checked */
+extern int check_scope;
+
/* JYG: lookup rtti type of STRUCTOP_PTR when this is set to continue
on with successful lookup for member/method of the rtti type. */
extern int objectprint;

/* Prototypes for local functions. */
+static struct value *evaluate_subexp_for_scope (struct expression *, int *);

static struct value *evaluate_subexp_for_sizeof (struct expression *, int *);

@@ -162,7 +166,24 @@
evaluate_expression (struct expression *exp)
{
int pc = 0;
- return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_NORMAL);
+
+ /* Modifications so that if we are checking scope we can
+ reset the value of the variable to 0, so we don't check
+ scope when we don't want to */
+ struct value *val = NULL;
+ if(check_scope == 1)
+ {
+ val = evaluate_subexp_for_scope(exp, &pc);
+ }
+ else
+ {
+ val = evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_NORMAL);
+ }
+
+ if(check_scope == 1)
+ check_scope = 0;
+
+ return val;
}

/* Evaluate an expression, avoiding all memory references
@@ -443,12 +464,15 @@
&exp->elts[pc + 3].string,
0, noside);
if (arg1 == NULL)
- error (_("There is no field named %s"), &exp->elts[pc + 3].string);
+ {
+ error (_("There is no field named %s"), &exp->elts[pc + 3].string);
+ }
+
return arg1;

case OP_LONG:
(*pos) += 3;
- return value_from_longest (exp->elts[pc + 1].type,
+ return value_from_longest (exp->elts[pc + 1].type,
exp->elts[pc + 2].longconst);

case OP_DOUBLE:
@@ -461,7 +485,7 @@
return value_from_decfloat (expect_type, exp->elts[pc + 1].type,
exp->elts[pc + 2].decfloatconst);

- case OP_VAR_VALUE:
+ case OP_VAR_VALUE:
(*pos) += 3;
if (noside == EVAL_SKIP)
goto nosideret;
@@ -495,7 +519,7 @@

return ret;
}
-
+
case OP_LAST:
(*pos) += 2;
return
@@ -523,20 +547,22 @@
}
case OP_BOOL:
(*pos) += 2;
- return value_from_longest (LA_BOOL_TYPE,
- exp->elts[pc + 1].longconst);
+ return value_from_longest (LA_BOOL_TYPE,
+ exp->elts[pc + 1].longconst);
+

case OP_INTERNALVAR:
(*pos) += 2;
- return value_of_internalvar (exp->elts[pc + 1].internalvar);
+ return value_of_internalvar (exp->elts[pc + 1].internalvar);
+

case OP_STRING:
tem = longest_to_int (exp->elts[pc + 1].longconst);
(*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
if (noside == EVAL_SKIP)
goto nosideret;
- return value_string (&exp->elts[pc + 2].string, tem);
-
+ return value_string (&exp->elts[pc + 2].string, tem);
+
case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant. */
tem = longest_to_int (exp->elts[pc + 1].longconst);
(*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
@@ -544,6 +570,7 @@
{
goto nosideret;
}
+
return (struct value *) value_nsstring (&exp->elts[pc + 2].string, tem + 1);

case OP_BITSTRING:
@@ -552,6 +579,7 @@
+= 3 + BYTES_TO_EXP_ELEM ((tem + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT);
if (noside == EVAL_SKIP)
goto nosideret;
+
return value_bitstring (&exp->elts[pc + 2].string, tem);
break;

@@ -1337,7 +1365,9 @@
case STRUCTOP_STRUCT:
tem = longest_to_int (exp->elts[pc + 1].longconst);
(*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
if (noside == EVAL_SKIP)
goto nosideret;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
@@ -1438,8 +1468,11 @@
case BINOP_CONCAT:
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
+ return value_binop (arg1, arg2, BINOP_LOGICAL_AND);
+
if (noside == EVAL_SKIP)
- goto nosideret;
+ goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
return value_x_binop (arg1, arg2, op, OP_NULL, noside);
else
@@ -1450,32 +1483,36 @@
arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);

if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
+ return arg1;
if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ return value_x_binop (arg1, arg2, op, OP_NULL, noside);
else
return value_assign (arg1, arg2);
-
+
+
case BINOP_ASSIGN_MODIFY:
(*pos) += 2;
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
arg2 = evaluate_subexp (value_type (arg1), exp, pos, noside);
+
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
+ return arg1;
+
op = exp->elts[pc + 1].opcode;
if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op, noside);
+ return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op, noside);
else if (op == BINOP_ADD)
- arg2 = value_add (arg1, arg2);
+ arg2 = value_add (arg1, arg2);
else if (op == BINOP_SUB)
- arg2 = value_sub (arg1, arg2);
+ arg2 = value_sub (arg1, arg2);
else
- arg2 = value_binop (arg1, arg2, op);
+ arg2 = value_binop (arg1, arg2, op);
return value_assign (arg1, arg2);

case BINOP_ADD:
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
if (noside == EVAL_SKIP)
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
@@ -1486,6 +1523,7 @@
case BINOP_SUB:
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
if (noside == EVAL_SKIP)
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
@@ -1505,6 +1543,7 @@
case BINOP_BITWISE_XOR:
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
if (noside == EVAL_SKIP)
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
@@ -1518,6 +1557,7 @@
case BINOP_RANGE:
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
if (noside == EVAL_SKIP)
goto nosideret;
error (_("':' operator used in invalid context"));
@@ -1525,6 +1565,7 @@
case BINOP_SUBSCRIPT:
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
if (noside == EVAL_SKIP)
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
@@ -1556,6 +1597,7 @@
case BINOP_IN:
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
if (noside == EVAL_SKIP)
goto nosideret;
return value_in (arg1, arg2);
@@ -1741,10 +1783,12 @@
else
{
tem = value_logical_not (arg1);
- arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
+
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
(!tem ? EVAL_SKIP : noside));
+
return value_from_longest (LA_BOOL_TYPE,
- (LONGEST) (!tem || !value_logical_not (arg2)));
+ (LONGEST) (!tem || !value_logical_not (arg2)));
}

case BINOP_EQUAL:
@@ -2085,7 +2129,202 @@
nosideret:
return value_from_longest (builtin_type_long, (LONGEST) 1);
}
-\f
+
+/* Evaluate a subexpression to see if the expression
+ * is in scope. Some special case scope checking
+ * remains in evaluate_subexp_standard(). */
+static struct value *
+evaluate_subexp_for_scope (struct expression *exp, int *pos)
+{
+ struct value *arg1 = NULL;
+ struct value *arg2 = NULL;
+
+ int tem;
+ int pc = (*pos)++;
+ enum exp_opcode op = exp->elts[pc].opcode;
+
+ switch(op)
+ {
+ case OP_SCOPE:
+ tem = longest_to_int (exp->elts[pc + 2].longconst);
+ (*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1);
+
+ arg1 = value_aggregate_elt (exp->elts[pc + 1].type,
+ &exp->elts[pc + 3].string,
+ 0, EVAL_NORMAL);
+ if (arg1 == NULL)
+ return value_from_longest (builtin_type_int, (LONGEST) 0);
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ case OP_DECFLOAT:
+ case OP_VAR_VALUE:
+ (*pos) += 3;
+
+ /* Special case, if a variable is not in scope the parser
+ * puts an expression of value 0. If the expression is
+ * of value 0, return one aof 0, else return a vlaue of 1.
+ */
+ if(exp->elts[pc + 2].longconst == 0)
+ return value_from_longest (builtin_type_int, (LONGEST) 0);
+ else
+ return value_from_longest (builtin_type_int, (LONGEST) 1);
+
+ case OP_LAST:
+ case OP_INTERNALVAR:
+ (*pos) += 2;
+ return value_from_longest (builtin_type_int, (LONGEST) 1);
+
+ case OP_REGISTER:
+ {
+ const char *name = &exp->elts[pc + 2].string;
+ int regno;
+ struct value *val;
+
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1);
+ regno = frame_map_name_to_regnum (deprecated_safe_get_selected_frame (),
+ name, strlen (name));
+
+ if (regno == -1)
+ return value_from_longest (builtin_type_int, (LONGEST) 0);
+
+ val = value_of_register (regno, get_selected_frame (NULL));
+
+ if (val == NULL)
+ return value_from_longest (builtin_type_int, (LONGEST) 0);
+ else
+ return value_from_longest (builtin_type_int, (LONGEST) 1);
+ }
+ case OP_STRING:
+ case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant. */
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+
+ return value_from_longest (builtin_type_int, (LONGEST) 1);
+
+ case OP_BITSTRING:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos)
+ += 3 + BYTES_TO_EXP_ELEM ((tem + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT);
+
+ return value_from_longest (builtin_type_int, (LONGEST) 1);
+
+ /* FIXME: Unsure of how to check scope for these, so deal wiht them normally */
+ case OP_ARRAY:
+ case TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
+ case TERNOP_COND:
+ case OP_OBJC_SELECTOR:
+ case OP_OBJC_MSGCALL:
+ case OP_FUNCALL:
+ case OP_F77_UNDETERMINED_ARGLIST:
+ case STRUCTOP_PTR:
+ case STRUCTOP_MEMBER:
+ case STRUCTOP_MPTR:
+/* case TYPE_CODE_METHODPTR:
+ case TYPE_CODE_MEMBERPTR: */
+ case MULTI_SUBSCRIPT:
+ case UNOP_IND:
+ return evaluate_subexp(NULL_TYPE, exp, pos, EVAL_NORMAL);
+
+ case STRUCTOP_STRUCT:
+
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+
+ /* Evaluate the sub-expression without scope so that the
+ * correct type of value is returned */
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
+ {
+ struct value *temp;
+ temp = arg1;
+ return value_struct_elt (&temp, NULL, &exp->elts[pc + 2].string,
+ NULL, "structure");
+ }
+ /* An expression which involves a binary operator is in scope
+ * iff it's two sub expressions are in scope. OP_COMPLEX
+ * is also regared as a binary operator in this respect. */
+ case BINOP_CONCAT:
+ case BINOP_ASSIGN:
+ case BINOP_ASSIGN_MODIFY:
+ case BINOP_ADD:
+ case BINOP_SUB:
+ case BINOP_EXP:
+ case BINOP_MUL:
+ case BINOP_DIV:
+ case BINOP_REM:
+ case BINOP_MOD:
+ case BINOP_LSH:
+ case BINOP_RSH:
+ case BINOP_BITWISE_AND:
+ case BINOP_BITWISE_IOR:
+ case BINOP_BITWISE_XOR:
+ case BINOP_RANGE:
+ case BINOP_SUBSCRIPT:
+ case BINOP_IN:
+ case BINOP_LOGICAL_AND:
+ case BINOP_LOGICAL_OR:
+ case BINOP_EQUAL:
+ case BINOP_NOTEQUAL:
+ case BINOP_LESS:
+ case BINOP_GTR:
+ case BINOP_GEQ:
+ case BINOP_LEQ:
+ case BINOP_REPEAT:
+ case BINOP_COMMA:
+ case OP_COMPLEX:
+ arg1 = evaluate_subexp_for_scope (exp, pos);
+ arg2 = evaluate_subexp_for_scope (exp, pos);
+
+ return value_binop (arg1, arg2, BINOP_LOGICAL_AND);
+
+ case UNOP_PLUS:
+ case UNOP_NEG:
+ case UNOP_COMPLEMENT:
+ case UNOP_LOGICAL_NOT:
+ case UNOP_ADDR:
+ case UNOP_SIZEOF:
+ case UNOP_PREINCREMENT:
+ case UNOP_PREDECREMENT:
+ case UNOP_POSTINCREMENT:
+ case UNOP_POSTDECREMENT:
+ arg1 = evaluate_subexp_for_scope (exp, pos);
+ return arg1;
+
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ (*pos) += 2;
+ arg1 = evaluate_subexp_for_scope (exp, pos);
+ return arg1;
+
+ case UNOP_MEMVAL_TLS:
+ (*pos) += 3;
+ arg1 = evaluate_subexp_for_scope (exp, pos);
+ return arg1;
+
+ case OP_THIS:
+ (*pos) += 1;
+ return value_from_longest (builtin_type_int, (LONGEST) 1);
+
+ case OP_OBJC_SELF:
+ (*pos) += 1;
+ return value_from_longest (builtin_type_int, (LONGEST) 1);
+
+ default:
+ /* Removing this case and compiling with gcc -Wall reveals that
+ a lot of cases are hitting this case. Some of these should
+ probably be removed from expression.h; others are legitimate
+ expressions which are (apparently) not fully implemented.
+
+ If there are any cases landing here which mean a user error,
+ then they should be separate cases, with more descriptive
+ error messages. */
+
+ error (_("\
+GDB does not (yet) know how to evaluate that kind of expression for scope"));
+ }
+}
+
/* Evaluate a subexpression of EXP, at index *POS,
and return the address of that subexpression.
Advance *POS over the subexpression.