From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25431 invoked by alias); 16 Feb 2010 18:31:28 -0000 Received: (qmail 25422 invoked by uid 22791); 16 Feb 2010 18:31:26 -0000 X-SWARE-Spam-Status: No, hits=-7.0 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 16 Feb 2010 18:31:22 +0000 Received: from int-mx08.intmail.prod.int.phx2.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o1GIVKqM020961 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 16 Feb 2010 13:31:21 -0500 Received: from qcore.mollernet.net (vpn-234-95.phx2.redhat.com [10.3.234.95]) by int-mx08.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o1GIVKPq031553 for ; Tue, 16 Feb 2010 13:31:20 -0500 Message-ID: <4B7AE477.9060606@redhat.com> Date: Tue, 16 Feb 2010 18:31:00 -0000 From: Chris Moller User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b3pre) Gecko/20090513 Fedora/3.0-2.3.beta2.fc11 Thunderbird/3.0b2 MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: beta patch for PR 9065 Content-Type: multipart/mixed; boundary="------------080804070105070608000500" X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-02/txt/msg00388.txt.bz2 This is a multi-part message in MIME format. --------------080804070105070608000500 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1857 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 #include 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().name(), or the abbreviated form of typeid(). [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 = sizeof()". 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 --------------080804070105070608000500 Content-Type: text/plain; name="pr9065.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="pr9065.patch" Content-length: 6846 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; --------------080804070105070608000500--