* beta patch for PR 9065
@ 2010-02-16 18:31 Chris Moller
2010-02-16 21:53 ` Daniel Jacobowitz
2010-02-16 22:25 ` Tom Tromey
0 siblings, 2 replies; 6+ messages in thread
From: Chris Moller @ 2010-02-16 18:31 UTC (permalink / raw)
To: gdb-patches
[-- 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;
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: beta patch for PR 9065
2010-02-16 18:31 beta patch for PR 9065 Chris Moller
@ 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:25 ` Tom Tromey
1 sibling, 2 replies; 6+ messages in thread
From: Daniel Jacobowitz @ 2010-02-16 21:53 UTC (permalink / raw)
To: Chris Moller; +Cc: gdb-patches
On Tue, Feb 16, 2010 at 01:31:19PM -0500, Chris Moller wrote:
> [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...)]
What do folks use typeid for, in the wild? IMO, "ptype typeid(int)"
giving you a string would be very surprising.
It's been a while since I looked at this, but the typeinfo for a class
with RTTI should be available in the symbol table (_ZTI symbols). The
others might be available or not; we could look them up in the symbol
table, or allocate them dynamically.
We could synthesize a type_info object; the Itanium C++ ABI defines
the layout (section 2.9.5). But we might also have to synthesize its
name() method, as it is unlikely to be emitted out of line.
name() is supposed to return a mangled type name, too. I'm not sure
how able GDB is going to be to mangle type names; it's a very hard
problem w.r.t. templates.
The appliction or libstdc++ should have the typeinfos for anything
whose typeinfo was referenced...
> @@ -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},
I bet adding "name" to this list will break any expression with "name"
in it, like "print name".
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: beta patch for PR 9065
2010-02-16 21:53 ` Daniel Jacobowitz
@ 2010-02-16 22:02 ` Chris Moller
2010-02-16 22:27 ` Tom Tromey
1 sibling, 0 replies; 6+ messages in thread
From: Chris Moller @ 2010-02-16 22:02 UTC (permalink / raw)
To: gdb-patches
On 02/16/10 16:53, Daniel Jacobowitz wrote:
>
>> @@ -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},
>>
>
> I bet adding "name" to this list will break any expression with "name"
> in it, like "print name".
>
Yeah, that occurred to me about 30 seconds after I sent the patch out. :-)
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: beta patch for PR 9065
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
1 sibling, 1 reply; 6+ messages in thread
From: Tom Tromey @ 2010-02-16 22:27 UTC (permalink / raw)
To: Chris Moller; +Cc: gdb-patches
>>>>> "Daniel" == Daniel Jacobowitz <dan@codesourcery.com> writes:
Daniel> It's been a while since I looked at this, but the typeinfo for a class
Daniel> with RTTI should be available in the symbol table (_ZTI
Daniel> symbols).
Oh, right. Maybe I was confusing this w/ a vtable slot, whoops.
Daniel> We could synthesize a type_info object; the Itanium C++ ABI defines
Daniel> the layout (section 2.9.5). But we might also have to synthesize its
Daniel> name() method, as it is unlikely to be emitted out of line.
I think it would be acceptable, though not ideal, to give an error in
this situation.
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: beta patch for PR 9065
2010-02-16 22:27 ` Tom Tromey
@ 2010-02-16 22:57 ` Daniel Jacobowitz
0 siblings, 0 replies; 6+ messages in thread
From: Daniel Jacobowitz @ 2010-02-16 22:57 UTC (permalink / raw)
To: Tom Tromey; +Cc: Chris Moller, gdb-patches
On Tue, Feb 16, 2010 at 03:27:47PM -0700, Tom Tromey wrote:
> >>>>> "Daniel" == Daniel Jacobowitz <dan@codesourcery.com> writes:
>
> Daniel> It's been a while since I looked at this, but the typeinfo for a class
> Daniel> with RTTI should be available in the symbol table (_ZTI
> Daniel> symbols).
>
> Oh, right. Maybe I was confusing this w/ a vtable slot, whoops.
It's both, but there are also _ZTI symbols for things without vtables;
e.g. standard types ("int") and classes without a vtable but where
typeid was used. The vtable's probably preferable where available.
> Daniel> We could synthesize a type_info object; the Itanium C++ ABI defines
> Daniel> the layout (section 2.9.5). But we might also have to synthesize its
> Daniel> name() method, as it is unlikely to be emitted out of line.
>
> I think it would be acceptable, though not ideal, to give an error in
> this situation.
Yes - it's a more general problem - IMO it'd be nice to be able to
have scripts implement not-outlined methods. std::string.length() is
probably similar...
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: beta patch for PR 9065
2010-02-16 18:31 beta patch for PR 9065 Chris Moller
2010-02-16 21:53 ` Daniel Jacobowitz
@ 2010-02-16 22:25 ` Tom Tromey
1 sibling, 0 replies; 6+ messages in thread
From: Tom Tromey @ 2010-02-16 22:25 UTC (permalink / raw)
To: Chris Moller; +Cc: gdb-patches
>>>>> "Chris" == Chris Moller <cmoller@redhat.com> writes:
Chris> [Question: Internally, this patch is based on "sizeof" which actually
Chris> creates an int type that, in addition to just being printed, can be
Chris> used for stuff like "set <var> = sizeof(<whatever>)". The gdb typeid
Chris> doesn't even try to create an analogue to a type_info class, it just
Chris> extracts the name from the appropriate type struct and creates a
Chris> cstring type from it. Would it be good/essential for the
Chris> implementation to instantiate a real type_info class? (That, I
Chris> suspect, will be a lot more work...)]
I think it is reasonably important to find the type_info. Anything else
will yield results which violate the "cut and paste" rule. E.g., the
user might have a function that takes a `const type_info&' argument.
It may be reasonable to require the user to have libstdc++ debuginfo
installed in order for this to work. I would accept this as a first
patch (with the usual caveat that if new information arises, etc).
IIRC, the type_info object is stored in some vtable slot in the v3 ABI.
If that is in fact the case then we probably want a new cp-abi function
for this. In this situation, IMO it is ok for the v2 variant to throw
an exception (or not be implemented, same difference).
One additional possible gotcha is making sure that gdb gives a sensible
error message if the user compiled with -fno-rtti.
Chris> + {"typeid", TYPEID, OP_NULL, 0},
This is a C++ keyword, so the last field should be 1, not 0.
Chris> +static struct value *evaluate_subexp_for_typeid_type (struct expression *, int *);
Chris> +static struct value *evaluate_subexp_for_typeid_var (struct expression *, int *);
The new style is to put static functions above their uses so we don't
have to have forward declarations.
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-02-16 22:57 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-16 18:31 beta patch for PR 9065 Chris Moller
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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox