@@ -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"
@@ -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
@@ -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;
@@ -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,
@@ -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, \
@@ -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
new file mode 100644
@@ -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 } }