From patchwork Wed Mar 16 19:56:37 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 87297 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 83441B6FAC for ; Thu, 17 Mar 2011 06:57:17 +1100 (EST) Received: (qmail 17115 invoked by alias); 16 Mar 2011 19:57:02 -0000 Received: (qmail 16958 invoked by uid 22791); 16 Mar 2011 19:56:53 -0000 X-SWARE-Spam-Status: No, hits=-5.7 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_BJ, TW_JC, T_RP_MATCHES_RCVD 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; Wed, 16 Mar 2011 19:56:42 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p2GJueII020439 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 16 Mar 2011 15:56:40 -0400 Received: from localhost.localdomain ([10.3.113.6]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p2GJudA4014252 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 16 Mar 2011 15:56:40 -0400 Received: by localhost.localdomain (Postfix, from userid 500) id BC1048E604B; Wed, 16 Mar 2011 20:56:37 +0100 (CET) From: Dodji Seketeli To: Jason Merrill Cc: GCC Patches Subject: [PATCH] PR debug/28767 (Support pointer-to-member-function) X-URL: http://www.redhat.com Date: Wed, 16 Mar 2011 20:56:37 +0100 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hello, This PR is an enhancement request to emit a DW_TAG_ptr_to_member_type DIE for pointer-to-member-function types. The patch below does add a new language hook to support this and adapts the existing code that emits DW_TAG_ptr_to_member_type for ponter-to-data-member types to handle pointer-to-member-function types as well. Tested on x86_64-unknown-linux-gnu against trunk. I am proposing this for 4.7. diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index e5c1c09..62faa1c 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -40,7 +40,7 @@ static enum classify_record cp_classify_record (tree type); static tree cp_eh_personality (void); static tree get_template_innermost_arguments_folded (const_tree); static tree get_template_argument_pack_elems_folded (const_tree); - +static bool is_ptr_to_member (const_tree, tree*); /* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h; consequently, there should be very few hooks below. */ @@ -65,6 +65,9 @@ static tree get_template_argument_pack_elems_folded (const_tree); #undef LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS #define LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS \ get_template_argument_pack_elems_folded +#undef LANG_HOOKS_IS_PTR_TO_MEMBER +#define LANG_HOOKS_IS_PTR_TO_MEMBER \ + is_ptr_to_member #undef LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P #define LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P \ template_template_parameter_p @@ -238,5 +241,39 @@ get_template_argument_pack_elems_folded (const_tree t) return fold_cplus_constants (get_template_argument_pack_elems (t)); } +/* The C++ implementation of LANG_HOOKS_GET_PTRMEM_TYPES. + + Returns TRUE if T is a pointer-to-data-member or + a pointer-to-member-function. + + If PTRMEM_INFO is non-null and if T is a + pointer-to-member-function, *PTRMEM_INFO is set to a TREE_LIST + which TREE_PURPOSE is the METHOD_TYPE of member-function pointed + to. The TREE_VALUE is the class/struct type containing the member + function. If T is a pointer-to-member, *PTRMEM_INFO is set to a + TREE_LIST which TREE_PURPOSE is the type of the member, and which + TREE_VALUE is the class/strunct type containing the data member. + The TREE_TYPE is set to T. */ + +static bool +is_ptr_to_member (const_tree t, + tree *ptrmem_info) +{ + if (!t || !TYPE_PTR_TO_MEMBER_P (t)) + return false; + + if (ptrmem_info != NULL) + { + if (TYPE_PTRMEMFUNC_P (t)) + *ptrmem_info = build_tree_list (TYPE_PTRMEMFUNC_FN_TYPE (t), + TYPE_PTRMEMFUNC_OBJECT_TYPE (t)); + else + *ptrmem_info = build_tree_list (TYPE_PTRMEM_POINTED_TO_TYPE (t), + TYPE_PTRMEM_CLASS_TYPE (t)); + TREE_TYPE (*ptrmem_info) = CONST_CAST_TREE (t); + } + return true; +} + #include "gt-cp-cp-lang.h" #include "gtype-cp.h" diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 733c849..949c099 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -6520,7 +6520,7 @@ static void gen_label_die (tree, dw_die_ref); static void gen_lexical_block_die (tree, dw_die_ref, int); static void gen_inlined_subroutine_die (tree, dw_die_ref, int); static void gen_field_die (tree, dw_die_ref); -static void gen_ptr_to_mbr_type_die (tree, dw_die_ref); +static bool gen_ptr_to_mbr_type_die (tree, dw_die_ref); static dw_die_ref gen_compile_unit_die (const char *); static void gen_inheritance_die (tree, tree, dw_die_ref); static void gen_member_die (tree, dw_die_ref); @@ -20064,19 +20064,36 @@ gen_reference_type_die (tree type, dw_die_ref context_die) } #endif -/* Generate a DIE for a pointer to a member type. */ +/* Generate a DIE for a pointer to a member type. Return TRUE if the + DIE was actually generated, false otherwise. */ -static void +static bool gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die) { - dw_die_ref ptr_die - = new_die (DW_TAG_ptr_to_member_type, - scope_die_for (type, context_die), type); + dw_die_ref ptr_die; + tree ptrmem_info = NULL_TREE; + + if (!lang_hooks.types.is_ptr_to_member (type, &ptrmem_info)) + return false; + gcc_assert (ptrmem_info != NULL_TREE); + + /* Output the description of the class type containing the + member pointed to. */ + gen_type_die_with_usage (TREE_VALUE (ptrmem_info), + context_die, DINFO_USAGE_IND_USE); + /* Output the description of the type of the memeber + pointed to. */ + gen_type_die_with_usage (TREE_PURPOSE (ptrmem_info), + context_die, DINFO_USAGE_IND_USE); + /* Now create the DW_TAG_ptr_to_member_type proper. */ + ptr_die = new_die (DW_TAG_ptr_to_member_type, + scope_die_for (type, context_die), type); equate_type_number_to_die (type, ptr_die); add_AT_die_ref (ptr_die, DW_AT_containing_type, - lookup_type_die (TYPE_OFFSET_BASETYPE (type))); - add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die); + lookup_type_die (TREE_VALUE (ptrmem_info))); + add_type_attribute (ptr_die, TREE_PURPOSE (ptrmem_info), 0, 0, context_die); + return true; } /* Generate the DIE for the compilation unit. */ @@ -20603,6 +20620,14 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die, return; } + /* If this is a pointer-to-member, handle it here. */ + if (!TREE_ASM_WRITTEN (type) + && gen_ptr_to_mbr_type_die (type, context_die)) + { + TREE_ASM_WRITTEN (type) = 1; + return; + } + /* We are going to output a DIE to represent the unqualified version of this type (i.e. without any const or volatile qualifiers) so get the main variant (i.e. the unqualified version) of this type @@ -20635,19 +20660,9 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die, break; case OFFSET_TYPE: - /* This code is used for C++ pointer-to-data-member types. - Output a description of the relevant class type. */ - gen_type_die_with_usage (TYPE_OFFSET_BASETYPE (type), context_die, - DINFO_USAGE_IND_USE); - - /* Output a description of the type of the object pointed to. */ - gen_type_die_with_usage (TREE_TYPE (type), context_die, - DINFO_USAGE_IND_USE); - - /* Now output a DIE to represent this pointer-to-data-member type - itself. */ - gen_ptr_to_mbr_type_die (type, context_die); - break; + /* This code is used for C++ pointer-to-data-member types, so + it should have been handled earlier. */ + gcc_unreachable (); case FUNCTION_TYPE: /* Force out return type (in case it wasn't forced out already). */ @@ -21818,7 +21833,6 @@ gen_scheduled_generic_parms_dies (void) gen_generic_params_dies (t); } - /* Replace DW_AT_name for the decl with name. */ static void diff --git a/gcc/hooks.c b/gcc/hooks.c index f859dd9..4a2a9f2 100644 --- a/gcc/hooks.c +++ b/gcc/hooks.c @@ -219,6 +219,13 @@ hook_bool_const_tree_true (const_tree a ATTRIBUTE_UNUSED) } bool +hook_bool_const_tree_treeptr_false (const_tree a ATTRIBUTE_UNUSED, + tree *b ATTRIBUTE_UNUSED) +{ + return false; +} + +bool hook_bool_tree_tree_false (tree a ATTRIBUTE_UNUSED, tree b ATTRIBUTE_UNUSED) { return false; diff --git a/gcc/hooks.h b/gcc/hooks.h index 7962fe8..71fe747 100644 --- a/gcc/hooks.h +++ b/gcc/hooks.h @@ -38,6 +38,7 @@ extern bool hook_bool_tree_false (tree); extern bool hook_bool_const_tree_false (const_tree); extern bool hook_bool_tree_true (tree); extern bool hook_bool_const_tree_true (const_tree); +extern bool hook_bool_const_tree_treeptr_false (const_tree, tree *p); extern bool hook_bool_const_tree_hwi_hwi_const_tree_false (const_tree, HOST_WIDE_INT, HOST_WIDE_INT, diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index 961e929..ab077f8 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -164,6 +164,7 @@ extern tree lhd_make_node (enum tree_code); #define LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS hook_tree_const_tree_null #define LANG_HOOKS_FUNCTION_PARAMETER_PACK_P hook_bool_const_tree_false #define LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS hook_tree_const_tree_null +#define LANG_HOOKS_IS_PTR_TO_MEMBER hook_bool_const_tree_treeptr_false #define LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P hook_bool_const_tree_false #define LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P \ hook_bool_tree_tree_false @@ -185,6 +186,7 @@ extern tree lhd_make_node (enum tree_code); LANG_HOOKS_TYPE_FOR_SIZE, \ LANG_HOOKS_GENERIC_TYPE_P, \ LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS, \ + LANG_HOOKS_IS_PTR_TO_MEMBER, \ LANG_HOOKS_TYPE_PROMOTES_TO, \ LANG_HOOKS_REGISTER_BUILTIN_TYPE, \ LANG_HOOKS_INCOMPLETE_TYPE_ERROR, \ diff --git a/gcc/langhooks.h b/gcc/langhooks.h index a994729..97758d6 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -90,6 +90,14 @@ struct lang_hooks_for_types /* Returns the TREE_VEC of elements of a given generic argument pack. */ tree (*get_argument_pack_elems) (const_tree); + /* If the first parameter is a pointer-to-data-member or a + pointer-to-function-member, return TRUE. If the second parameter + is non-null, set it to a TREE_LIST. The TREE_PURPOSE is the type + of the member pointed to. The TREE_VALUE is the type of the + class containing the member. The TREE_TYPE is set to the first + parameter. */ + bool (*is_ptr_to_member) (const_tree, tree*); + /* Given a type, apply default promotions to unnamed function arguments and return the new type. Return the same type if no change. Required by any language that supports variadic diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/ptrmem-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/ptrmem-1.C new file mode 100644 index 0000000..c232165 --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/dwarf2/ptrmem-1.C @@ -0,0 +1,20 @@ +// Origin PR debug/28767 +// { dg-options "-g -dA -fno-merge-debug-strings" } + +struct A +{ + int func(void); + char data; +}; + +int (A::*ptr) (void) = &A::func; +char A::* d = &A::data; + +// For the code abobe we want to test that we have two sequences +// ressembling: +// +// .uleb128 0x9 # (DIE (0x7f) DW_TAG_ptr_to_member_type) +// .long 0x2d # DW_AT_containing_type +// .long 0x88 # DW_AT_type +// +// { dg-final { scan-assembler-times "DIE \\(\[^\n\r\]+\\) DW_TAG_ptr_to_member_type\\)\[\n\r\]{1,2}\[^\n\r\]+DW_AT_containing_type\[^\n\r\]*\[\n\r\]{1,2}\[^\n\r\]+DW_AT_type\[^\n\r\]*\[\n\r\]{1,2}" 2 } }