On Tue, May 3, 2011 at 10:36 PM, Dodji Seketeli <do...@seketeli.org> wrote: > FWIW, this was posted to > http://gcc.gnu.org/ml/gcc-patches/2011-03/msg00949.html > > > > ---------- Forwarded message ---------- > From: Dodji Seketeli <do...@redhat.com> > To: Jason Merrill <ja...@redhat.com> > Date: Wed, 16 Mar 2011 20:56:37 +0100 > Subject: [PATCH] PR debug/28767 (Support pointer-to-member-function) > 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. > > -- > Dodji > > From 36d971de3a01c83f8e23c4016262ea73357f6bd6 Mon Sep 17 00:00:00 2001 > From: Dodji Seketeli <do...@redhat.com> > Date: Tue, 15 Mar 2011 16:50:30 +0100 > Subject: [PATCH] PR debug/28767 (Support pointer-to-member-function) > > gcc/ > * langhooks.h (struct lag_hooks_for_type)<is_ptr_to_member>: > Declare New language hook. > * hooks.h (hook_bool_const_tree_treeptr_false): Declare ... > hooks.c (hook_bool_const_tree_treeptr_false): ... new default > hook. > * langhooks-def.h (LANG_HOOKS_IS_PTR_TO_MEMBER): Define new hook > initializer.
Ick. Can you please instead grab some available bit in TREE_TYPE instead of using a new langhook which makes it impossible to support this from LTO? Richard. > (LANG_HOOKS_FOR_TYPES_INITIALIZER): Initialize the > is_ptr_to_member field to LANG_HOOKS_IS_PTR_TO_MEMBER. > * dwarf2out.c (gen_ptr_to_mbr_type_die): Handle > pointer-to-member-function in addition to pointer-to-data-member. > Both using the new language hook. > (gen_type_die_with_usage): Handle pointer-to-member-function and > pointer-to-data-member types with gen_ptr_to_mbr_type_die. > > gcc/cp/ > > * cp-lang.c (is_ptr_to_member): New language hook implementation > for C++. > (LANG_HOOKS_IS_PTR_TO_MEMBER): Initialize this language hook for > C++. > > gcc/testsuite/ > > * g++.dg/debug/dwarf2/ptrmem-1.C: New test. > --- > gcc/cp/cp-lang.c | 39 +++++++++++++++++- > gcc/dwarf2out.c | 58 > ++++++++++++++++---------- > gcc/hooks.c | 7 +++ > gcc/hooks.h | 1 + > gcc/langhooks-def.h | 2 + > gcc/langhooks.h | 8 ++++ > gcc/testsuite/g++.dg/debug/dwarf2/ptrmem-1.C | 20 +++++++++ > 7 files changed, 112 insertions(+), 23 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/ptrmem-1.C > > 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 } } > -- > 1.7.3.4 > > > > > -- > Dodji > >