From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26851 invoked by alias); 27 Jul 2010 21:17:28 -0000 Received: (qmail 26837 invoked by uid 22791); 27 Jul 2010 21:17:25 -0000 X-SWARE-Spam-Status: No, hits=-2.0 required=5.0 tests=AWL,BAYES_00,TW_PM,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 27 Jul 2010 21:17:19 +0000 Received: (qmail 21628 invoked from network); 27 Jul 2010 21:17:17 -0000 Received: from unknown (HELO orlando.localnet) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 27 Jul 2010 21:17:17 -0000 From: Pedro Alves To: gdb-patches@sourceware.org, Daniel Jacobowitz Subject: Improve 'this' detection Date: Tue, 27 Jul 2010 21:17:00 -0000 User-Agent: KMail/1.13.2 (Linux/2.6.32-24-generic; KDE/4.4.2; x86_64; ; ) MIME-Version: 1.0 Content-Type: Text/Plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Message-Id: <201007272217.14220.pedro@codesourcery.com> 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-07/txt/msg00448.txt.bz2 This patch of Daniel's improves THIS detection in C++ method's parameters. The user visible change is that GDB now presents the `this' parameter type const qualified. (gdb) ptype pmf type = int (A::*)(A *, int) (gdb) ptype pmf type = int (A::*)(A * const, int) We needed tweaks for GCC and RealView. For GCC, this works around GCC PR 43053, where GCC marks THIS as const in method definitions, but not in the class specifications. RealView also doesn't mark THIS as const, but it does output DW_AT_object_pointer, which we can use to cleanly identify `this'. I was going to ask if you think we should tweak the testsuite patch to always expect "const", instead of the current optional "( const)?", but I remembered not the whole world is dwarf yet :-) The patch looked pretty reasonable to me. Tested on x86_64-linux. Comments? -- Pedro Alves 2010-07-27 Daniel Jacobowitz gdb/ * dwarf2read.c (read_subroutine_type): Improve THIS detection, handling DW_AT_object_pointer, and workaround GCC PR 43053. gdb/testsuite/ * gdb.cp/member-ptr.exp, gdb.cp/printmethod.exp, gdb.dwarf2/member-ptr-forwardref.exp: Adjust. --- gdb/dwarf2read.c | 51 ++++++++++++++++++--- gdb/testsuite/gdb.cp/member-ptr.exp | 22 ++++----- gdb/testsuite/gdb.cp/printmethod.exp | 4 - gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp | 2 4 files changed, 59 insertions(+), 20 deletions(-) Index: src/gdb/dwarf2read.c =================================================================== --- src.orig/gdb/dwarf2read.c 2010-07-27 20:28:25.000000000 +0100 +++ src/gdb/dwarf2read.c 2010-07-27 21:50:37.000000000 +0100 @@ -7319,11 +7319,17 @@ read_subroutine_type (struct die_info *d { if (child_die->tag == DW_TAG_formal_parameter) { - /* Dwarf2 has no clean way to discern C++ static and non-static - member functions. G++ helps GDB by marking the first - parameter for non-static member functions (which is the - this pointer) as artificial. We pass this information - to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. */ + struct type *arg_type; + + /* DWARF version 2 has no clean way to discern C++ + static and non-static member functions. G++ helps + GDB by marking the first parameter for non-static + member functions (which is the this pointer) as + artificial. We pass this information to + dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. + + DWARF version 3 added DW_AT_object_pointer, which GCC + 4.5 does not yet generate. */ attr = dwarf2_attr (child_die, DW_AT_artificial, cu); if (attr) TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr); @@ -7341,7 +7347,40 @@ read_subroutine_type (struct die_info *d TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 1; } } - TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, cu); + arg_type = die_type (child_die, cu); + + /* RealView does not mark THIS as const, which the testsuite + expects. GCC marks THIS as const in method definitions, + but not in the class specifications (GCC PR 43053). */ + if (cu->language == language_cplus && !TYPE_CONST (arg_type) + && TYPE_FIELD_ARTIFICIAL (ftype, iparams)) + { + int is_this = 0; + struct dwarf2_cu *arg_cu = cu; + const char *name = dwarf2_name (child_die, cu); + + attr = dwarf2_attr (die, DW_AT_object_pointer, cu); + if (attr) + { + /* If the compiler emits this, use it. */ + if (follow_die_ref (die, attr, &arg_cu) == child_die) + is_this = 1; + } + else if (name && strcmp (name, "this") == 0) + /* Function definitions will have the argument names. */ + is_this = 1; + else if (name == NULL && iparams == 0) + /* Declarations may not have the names, so like + elsewhere in GDB, assume an artificial first + argument is "this". */ + is_this = 1; + + if (is_this) + arg_type = make_cv_type (1, TYPE_VOLATILE (arg_type), + arg_type, 0); + } + + TYPE_FIELD_TYPE (ftype, iparams) = arg_type; iparams++; } child_die = sibling_die (child_die); Index: src/gdb/testsuite/gdb.cp/member-ptr.exp =================================================================== --- src.orig/gdb/testsuite/gdb.cp/member-ptr.exp 2010-07-27 20:28:25.000000000 +0100 +++ src/gdb/testsuite/gdb.cp/member-ptr.exp 2010-07-27 21:25:09.000000000 +0100 @@ -396,7 +396,7 @@ gdb_test_multiple "print ((int) pmi) == set name "ptype pmf" gdb_test_multiple "ptype pmf" $name { - -re "type = int \\( ?A::\\*\\)\\(A \\*, int\\)\r\n$gdb_prompt $" { + -re "type = int \\( ?A::\\*\\)\\(A \\*( const)?, int\\)\r\n$gdb_prompt $" { pass $name } -re "type = int \\( ?A::\\*\\)\\(void\\)\r\n$gdb_prompt $" { @@ -418,7 +418,7 @@ gdb_test_multiple "ptype pmf" $name { set name "print pmf" gdb_test_multiple "print pmf" $name { - -re "$vhn = \\(int \\(A::\\*\\)\\(A \\*, int\\)\\) $hex \r\n$gdb_prompt $" { + -re "$vhn = \\(int \\(A::\\*\\)\\(A \\*( const)?, int\\)\\) $hex \r\n$gdb_prompt $" { pass $name } -re "$vhn = .*not supported with HP aCC.*\r\n$gdb_prompt $" { @@ -440,7 +440,7 @@ gdb_test_multiple "print pmf" $name { set name "ptype pmf_p" gdb_test_multiple "ptype pmf_p" $name { - -re "type = int \\( ?A::\\*\\*\\)\\(A \\*, int\\)\r\n$gdb_prompt $" { + -re "type = int \\( ?A::\\*\\*\\)\\(A \\*( const)?, int\\)\r\n$gdb_prompt $" { pass $name } -re "type = int \\( ?A::\\*\\*\\)\\(void\\)\r\n$gdb_prompt $" { @@ -482,7 +482,7 @@ gdb_test_multiple "print pmf_p" $name { set name "print a.*pmf" gdb_test_multiple "print a.*pmf" $name { - -re "$vhn = {int \\(A \\*, int\\)} $hex \r\n$gdb_prompt $" { + -re "$vhn = {int \\(A \\*( const)?, int\\)} $hex \r\n$gdb_prompt $" { pass $name } -re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" { @@ -504,7 +504,7 @@ gdb_test_multiple "print a.*pmf" $name { set name "print a_p->*pmf" gdb_test_multiple "print a_p->*pmf" $name { - -re "$vhn = {int \\(A \\*, int\\)} $hex \r\n$gdb_prompt $" { + -re "$vhn = {int \\(A \\*( const)?, int\\)} $hex \r\n$gdb_prompt $" { pass $name } -re "Pointers to methods not supported with HP aCC\r\n$gdb_prompt $" { @@ -606,7 +606,7 @@ gdb_test_multiple "print (a.*pmf)(3)" $n } } -gdb_test "ptype a.*pmf" "type = int \\(A \\*, int\\)" +gdb_test "ptype a.*pmf" "type = int \\(A \\*( const)?, int\\)" # Print out a pointer to data member which requires looking into # a base class. @@ -618,9 +618,9 @@ gdb_test "print diamond.*diamond_pmi" "$ # These two have a different object adjustment, but call the same method. gdb_test "print diamond.*left_pmf" \ - "$vhn = {int \\(Diamond \\*\\)} $hex " + "$vhn = {int \\(Diamond \\*( const)?\\)} $hex " gdb_test "print diamond.*right_pmf" \ - "$vhn = {int \\(Diamond \\*\\)} $hex " + "$vhn = {int \\(Diamond \\*( const)?\\)} $hex " gdb_test "print (diamond.*left_pmf) ()" "$vhn = 77" gdb_test "print (diamond.*right_pmf) ()" "$vhn = 88" @@ -628,9 +628,9 @@ gdb_test "print (diamond.*right_pmf) ()" # These two point to different methods, although they have the same # virtual table offsets. gdb_test "print diamond.*left_vpmf" \ - "$vhn = {int \\(Diamond \\*\\)} $hex " + "$vhn = {int \\(Diamond \\*( const)?\\)} $hex " gdb_test "print diamond.*right_vpmf" \ - "$vhn = {int \\(Diamond \\*\\)} $hex " + "$vhn = {int \\(Diamond \\*( const)?\\)} $hex " gdb_test "print (diamond.*left_vpmf) ()" "$vhn = 177" gdb_test "print (diamond.*left_base_vpmf) ()" "$vhn = 2077" @@ -658,5 +658,5 @@ gdb_test "print null_pmi = &A::j" "$vhn gdb_test "print null_pmi = 0" "$vhn = NULL" gdb_test "print null_pmf" "$vhn = NULL" -gdb_test "print null_pmf = &A::foo" "$vhn = \\(int \\(A::\\*\\)\\(A \\*, int\\)\\) $hex " +gdb_test "print null_pmf = &A::foo" "$vhn = \\(int \\(A::\\*\\)\\(A \\*( const)?, int\\)\\) $hex " gdb_test "print null_pmf = 0" "$vhn = NULL" Index: src/gdb/testsuite/gdb.cp/printmethod.exp =================================================================== --- src.orig/gdb/testsuite/gdb.cp/printmethod.exp 2010-07-27 20:28:25.000000000 +0100 +++ src/gdb/testsuite/gdb.cp/printmethod.exp 2010-07-27 21:25:09.000000000 +0100 @@ -62,10 +62,10 @@ gdb_continue_to_breakpoint "end of const # The first of these is for PR gdb/653. gdb_test "print theA->virt" \ - "\\$\[0-9\]* = {void \\(A \\*\\)} $hex " \ + "\\$\[0-9\]* = {void \\(A \\* const\\)} $hex " \ "print virtual method." gdb_test "print theA->nonvirt" \ - "\\$\[0-9\]* = {void \\(A \\*\\)} $hex " \ + "\\$\[0-9\]* = {void \\(A \\* const\\)} $hex " \ "print nonvirtual method." gdb_exit Index: src/gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp =================================================================== --- src.orig/gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp 2010-07-27 20:28:25.000000000 +0100 +++ src/gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp 2010-07-27 21:25:09.000000000 +0100 @@ -45,4 +45,4 @@ gdb_test "show cp-abi" {The currently se gdb_load ${binfile} -gdb_test "ptype c" "type = struct C {\[\r\n \t\]*private:\[\r\n \t\]*int \\(C::\\*fp\\)\\(C \\*\\);\[\r\n \t\]*}" +gdb_test "ptype c" "type = struct C {\[\r\n \t\]*private:\[\r\n \t\]*int \\(C::\\*fp\\)\\(C \\*( const)?\\);\[\r\n \t\]*}"