Index: gdb/c-exp.y =================================================================== RCS file: /cvs/src/src/gdb/c-exp.y,v retrieving revision 1.70 diff -u -r1.70 c-exp.y --- gdb/c-exp.y 10 Feb 2010 18:57:21 -0000 1.70 +++ gdb/c-exp.y 16 Feb 2010 17:59:21 -0000 @@ -162,7 +162,7 @@ %type exp exp1 type_exp start variable qualified_name lcurly %type rcurly -%type type typebase qualified_type +%type type typebase qualified_type typeid_type %type nonempty_typelist /* %type block */ @@ -201,7 +201,7 @@ %token NAME_OR_INT %token OPERATOR -%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON +%token STRUCT CLASS UNION ENUM SIZEOF TYPEID NAMELIT UNSIGNED COLONCOLON %token TEMPLATE %token ERROR %token NEW DELETE @@ -307,6 +307,19 @@ { write_exp_elt_opcode (UNOP_SIZEOF); } ; + + + +exp : typeid_exp %prec UNARY + { write_exp_elt_opcode (UNOP_TYPEID_VAR); } + ; + +typeid_exp : TYPEID exp + | TYPEID exp '.' NAMELIT '(' ')' + ; + + + exp : exp ARROW name { write_exp_elt_opcode (STRUCTOP_PTR); write_exp_string ($3); @@ -592,6 +605,19 @@ write_exp_elt_opcode (OP_LONG); } ; +exp : typeid_type %prec UNARY + { write_exp_elt_opcode (UNOP_TYPEID_TYPE); + CHECK_TYPEDEF ($1); + write_exp_elt_type ($1); + write_exp_elt_opcode (UNOP_TYPEID_TYPE); } + ; + +typeid_type : TYPEID '(' type ')' + {$$ = $3;} + | TYPEID '(' type ')' '.' NAMELIT '(' ')' + {$$ = $3;} + ; + exp : REINTERPRET_CAST '<' type '>' '(' exp ')' %prec UNARY { write_exp_elt_opcode (UNOP_REINTERPRET_CAST); write_exp_elt_type ($3); @@ -1897,6 +1923,8 @@ {"struct", STRUCT, OP_NULL, 0}, {"signed", SIGNED_KEYWORD, OP_NULL, 0}, {"sizeof", SIZEOF, OP_NULL, 0}, + {"typeid", TYPEID, OP_NULL, 0}, + {"name", NAMELIT, OP_NULL, 0}, {"double", DOUBLE_KEYWORD, OP_NULL, 0}, {"false", FALSEKEYWORD, OP_NULL, 1}, {"class", CLASS, OP_NULL, 1}, Index: gdb/eval.c =================================================================== RCS file: /cvs/src/src/gdb/eval.c,v retrieving revision 1.127 diff -u -r1.127 eval.c --- gdb/eval.c 8 Feb 2010 20:55:42 -0000 1.127 +++ gdb/eval.c 16 Feb 2010 17:59:23 -0000 @@ -55,6 +55,9 @@ static struct value *evaluate_subexp_for_sizeof (struct expression *, int *); +static struct value *evaluate_subexp_for_typeid_type (struct expression *, int *); +static struct value *evaluate_subexp_for_typeid_var (struct expression *, int *); + static struct value *evaluate_subexp_for_address (struct expression *, int *, enum noside); @@ -2468,6 +2471,22 @@ } return evaluate_subexp_for_sizeof (exp, pos); + case UNOP_TYPEID_TYPE: + if (noside == EVAL_SKIP) + { + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + goto nosideret; + } + return evaluate_subexp_for_typeid_type (exp, pos); + + case UNOP_TYPEID_VAR: + if (noside == EVAL_SKIP) + { + evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP); + goto nosideret; + } + return evaluate_subexp_for_typeid_var (exp, pos); + case UNOP_CAST: (*pos) += 2; type = exp->elts[pc + 1].type; @@ -2856,6 +2875,95 @@ } } +/* Evaluate a subexpression of EXP, at index *POS, + and return a value for the typeid of that subexpression. + Advance *POS over the subexpression. */ + +static struct value * +evaluate_subexp_for_typeid_var (struct expression *exp, int *pos) +{ + enum exp_opcode op; + char * type_name; + int pc; + struct type *typeid_type; + struct type *type; + struct value *val; + + typeid_type = language_string_char_type (exp->language_defn, exp->gdbarch); + + pc = (*pos); + op = exp->elts[pc].opcode; + + type = NULL; + + switch (op) + { + /* This case is handled specially + so that we avoid creating a value for the result type. + If the result type is very big, it's desirable not to + create a value unnecessarily. */ + case UNOP_IND: + (*pos)++; + val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); + type = check_typedef (value_type (val)); + if (TYPE_CODE (type) != TYPE_CODE_PTR + && TYPE_CODE (type) != TYPE_CODE_REF + && TYPE_CODE (type) != TYPE_CODE_ARRAY) + error (_("Attempt to take contents of a non-pointer value.")); + type = check_typedef (TYPE_TARGET_TYPE (type)); + break; + + case UNOP_MEMVAL: + (*pos) += 3; + type = check_typedef (exp->elts[pc + 1].type); + break; + + case OP_VAR_VALUE: + (*pos) += 4; + type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol)); + break; + + default: + val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); + type = check_typedef (value_type (val)); + break; + } + + if (TYPE_NAME (type)) + type_name = TYPE_NAME (type); + else if (TYPE_TAG_NAME (type)) + type_name = TYPE_TAG_NAME (type); + else + type_name = ""; + + return value_cstring (type_name, 1+strlen (type_name), typeid_type); +} + +static struct value * +evaluate_subexp_for_typeid_type (struct expression *exp, int *pos) +{ + char * type_name; + struct type *type; + int pc; + struct type *typeid_type; + + pc = (*pos); + (*pos) += 3; + + type = exp->elts[pc].type; + + if (TYPE_NAME (type)) + type_name = TYPE_NAME (type); + else if (TYPE_TAG_NAME (type)) + type_name = TYPE_TAG_NAME (type); + else + type_name = ""; + + typeid_type = language_string_char_type (exp->language_defn, exp->gdbarch); + + return value_cstring (type_name, 1+strlen (type_name), typeid_type); +} + /* Parse a type expression in the string [P..P+LENGTH). */ struct type * Index: gdb/expression.h =================================================================== RCS file: /cvs/src/src/gdb/expression.h,v retrieving revision 1.34 diff -u -r1.34 expression.h --- gdb/expression.h 18 Jan 2010 20:54:33 -0000 1.34 +++ gdb/expression.h 16 Feb 2010 17:59:23 -0000 @@ -265,6 +265,8 @@ UNOP_PREDECREMENT, /* -- before an expression */ UNOP_POSTDECREMENT, /* -- after an expression */ UNOP_SIZEOF, /* Unary sizeof (followed by expression) */ + UNOP_TYPEID_TYPE, /* Unary typeid (followed by expression) */ + UNOP_TYPEID_VAR, /* Unary typeid (followed by expression) */ UNOP_PLUS, /* Unary plus */ Index: gdb/parse.c =================================================================== RCS file: /cvs/src/src/gdb/parse.c,v retrieving revision 1.95 diff -u -r1.95 parse.c --- gdb/parse.c 10 Feb 2010 18:57:21 -0000 1.95 +++ gdb/parse.c 16 Feb 2010 17:59:24 -0000 @@ -860,6 +860,7 @@ case UNOP_MAX: case UNOP_MIN: + case UNOP_TYPEID_TYPE: oplen = 3; break;