From: Chris Moller <cmoller@redhat.com>
To: gdb-patches@sourceware.org
Subject: beta patch for PR 9065
Date: Tue, 16 Feb 2010 18:31:00 -0000 [thread overview]
Message-ID: <4B7AE477.9060606@redhat.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1857 bytes --]
This is a very early version of a patch I'm working on for
http://sourceware.org/bugzilla/show_bug.cgi?id=9065 to provide a typeid
capability in gdb. It's nowhere near done, but I'd like to put it out
there in case anyone objects wildly to what I'm doing or how I'm doing it.
What it does:
If you have some code from the source:
#include <iostream>
#include <typeinfo>
using namespace std;
struct A { virtual ~A() { } };
struct B : A { };
struct C { };
struct D : C { };
int main() {
B bobj;
A* ap = &bobj;
A& ar = bobj;
cout << "ap: " << typeid(*ap).name() << endl;
cout << "ar: " << typeid(ar).name() << endl;
D dobj;
C* cp = &dobj;
C& cr = dobj;
cout << "cp: " << typeid(*cp).name() << endl;
cout << "cr: " << typeid(cr).name() << endl;
}
this patch will let you do stuff like:
(gdb) p typeid(dobj)
$1 = "D"
(gdb) p typeid(dobj).name()
$2 = "D"
(gdb) p typeid(*ap).name()
$3 = "A"
(gdb)
In C++, typeid returns a reference to a class type_info, which contains
a member ".name()." Just for consistency with that, I've made this
implementation accept both a complete C++-like form of
typeid(<whatever>).name(), or the abbreviated form of typeid(<whatever>).
[Question: Internally, this patch is based on "sizeof" which actually
creates an int type that, in addition to just being printed, can be used
for stuff like "set <var> = sizeof(<whatever>)". The gdb typeid doesn't
even try to create an analogue to a type_info class, it just extracts
the name from the appropriate type struct and creates a cstring type
from it. Would it be good/essential for the implementation to
instantiate a real type_info class? (That, I suspect, will be a lot
more work...)]
Anyway, feedback welcome.
Chris
[-- Attachment #2: pr9065.patch --]
[-- Type: text/plain, Size: 6846 bytes --]
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 <voidval> exp exp1 type_exp start variable qualified_name lcurly
%type <lval> rcurly
-%type <tval> type typebase qualified_type
+%type <tval> type typebase qualified_type typeid_type
%type <tvec> nonempty_typelist
/* %type <bval> block */
@@ -201,7 +201,7 @@
%token <ssym> 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 = "<anonymous>";
+
+ 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 = "<anonymous>";
+
+ 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;
next reply other threads:[~2010-02-16 18:31 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-16 18:31 Chris Moller [this message]
2010-02-16 21:53 ` Daniel Jacobowitz
2010-02-16 22:02 ` Chris Moller
2010-02-16 22:27 ` Tom Tromey
2010-02-16 22:57 ` Daniel Jacobowitz
2010-02-16 22:25 ` Tom Tromey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B7AE477.9060606@redhat.com \
--to=cmoller@redhat.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox