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
>
>

Reply via email to