On Tue, May 3, 2011 at 10:36 PM, Dodji Seketeli <[email protected]> wrote:
> FWIW, this was posted to
> http://gcc.gnu.org/ml/gcc-patches/2011-03/msg00949.html
>
>
>
> ---------- Forwarded message ----------
> From: Dodji Seketeli <[email protected]>
> To: Jason Merrill <[email protected]>
> 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 <[email protected]>
> 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
>
>