Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
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;
 

             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