* [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those
@ 2016-11-02 14:31 Jakub Jelinek
2016-11-02 15:31 ` Jason Merrill
0 siblings, 1 reply; 8+ messages in thread
From: Jakub Jelinek @ 2016-11-02 14:31 UTC (permalink / raw)
To: Jason Merrill, Alexandre Oliva, Keith Seitz, Jan Kratochvil,
Pierre-Marie de Rodat
Cc: gcc-patches
Hi!
This is a merge of my patch from yesterday, Jason's incremental patch to
that and parts of Alex' patch from Oct 19.
It uses Alex' LANG_HOOKS_GET_PTRMEMFN_TYPE langhook. I've tried
to think about https://gcc.gnu.org/ml/gcc-patches/2011-05/msg00227.html
and we even have such a langhook now, modified_type_die
uses lang_hooks.types.get_debug_type, but
1) it is just called in modified_type_die and not in
gen_type_die_with_usage, that looks weird
2) it is used for something Ada-ish I really don't know how to test etc.
to be able to find out if it is safe to call it in
gen_type_die_with_usage too
3) most importantly, if the C++ version of this langhook would create
OFFSET_TYPE on the fly, I don't know how to ensure effective sharing
of DW_TAG_ptr_to_member_type nodes with the same DW_AT_type
and DW_AT_containing_type; unless the C++ langhook adds some extra
hash table that caches already created OFFSET_TYPEs or something similar,
it would create a new OFFSET_TYPE each time it is called
Also, I really don't know how well does GDB (especially older releases)
handle DW_TAG_ptr_to_member_type for PMF, so the patch wraps that currently
with if (dwarf_version >= 5). Quick grep revealed that GDB has code to
handle the __pfn/__delta fields. So, can I ask somebody from the GDB
team to test this patch with that if (dwarf_version >= 5) replaced
with if (1) and see if it works properly with current GDB as well as say
4-5 years old one (e.g. with -gdwarf-2 or -gdwarf-3)? If yes, we
should emit it unconditionally.
Bootstrapped/regtested on x86_64-linux and i686-linux, on the new ref-3.C
testcase emits the number of DIEs I really expect to. Ok for trunk?
2016-11-02 Jakub Jelinek <jakub@redhat.com>
Alexandre Oliva <aoliva@redhat.com>
Jason Merrill <jason@redhat.com>
PR debug/28767
PR debug/56974
* langhooks.h (struct lang_hooks_for_types): Document type_hash_eq
being also called on METHOD_TYPEs. Add type_dwarf_attribute and
get_ptrmemfn_type langhooks.
* langhooks.c (lhd_type_dwarf_attribute): New function.
* langhooks-def.h (lhd_type_dwarf_attribute): Declare.
(LANG_HOOKS_TYPE_DWARF_ATTRIBUTE, LANG_HOOKS_GET_PTRMEMFN_TYPE):
Define.
(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add
LANG_HOOKS_TYPE_DWARF_ATTRIBUTE and LANG_HOOKS_GET_PTRMEMFN_TYPE.
* hooks.h (hook_tree_const_tree_int_null): Declare.
* hooks.c (hook_tree_const_tree_int_null): New function.
* tree.h (check_lang_type): Declare.
* tree.c (check_lang_type): New function.
(check_qualified_type, check_aligned_type): Call it.
* dwarf2out.c (modified_type_die): Don't use type_main_variant
for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
check_base_type and check_lang_type.
(gen_ptr_to_mbr_type_die): Add class_type and member_type arguments,
allow type to be something other than OFFSET_TYPE, if lookup_type_die
is already non-NULL, return early. For OFFSET_TYPE add
DW_AT_use_location attribute.
(gen_subroutine_type_die): Add DW_AT_{,rvalue_}reference attribute
if needed.
(gen_type_die_with_usage): Don't use type_main_variant
for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
check_base_type and check_lang_type. Formatting fixes.
Adjust gen_ptr_to_mbr_type_die caller. Handle PMF.
cp/
* tree.c (cp_check_qualified_type): Use check_base_type and
TYPE_QUALS comparison instead of check_qualified_type.
(cxx_type_hash_eq): Return false if type_memfn_rqual don't match.
* cp-objcp-common.c (cp_get_ptrmemfn_type): New function.
(cp_decl_dwarf_attribute): Don't handle types here.
(cp_type_dwarf_attribute): New function.
* cp-objcp-common.h (cp_get_ptrmemfn_type, cp_type_dwarf_attribute):
Declare.
(LANG_HOOKS_GET_PTRMEMFN_TYPE, LANG_HOOKS_TYPE_DWARF_ATTRIBUTE):
Define.
testsuite/
* g++.dg/debug/dwarf2/ptrdmem-1.C: New test.
* g++.dg/debug/dwarf2/ref-3.C: New test.
* g++.dg/debug/dwarf2/refqual-1.C: New test.
* g++.dg/debug/dwarf2/refqual-2.C: New test.
--- gcc/langhooks.h.jj 2016-11-01 15:18:44.994506161 +0100
+++ gcc/langhooks.h 2016-11-02 11:43:51.905046755 +0100
@@ -120,7 +120,7 @@ struct lang_hooks_for_types
/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
Called only after doing all language independent checks.
At present, this function is only called when both TYPE1 and TYPE2 are
- FUNCTION_TYPEs. */
+ FUNCTION_TYPE or METHOD_TYPE. */
bool (*type_hash_eq) (const_tree, const_tree);
/* Return TRUE if TYPE uses a hidden descriptor and fills in information
@@ -162,6 +162,15 @@ struct lang_hooks_for_types
for the debugger about scale factor, etc. */
bool (*get_fixed_point_type_info) (const_tree,
struct fixed_point_type_info *);
+
+ /* Returns -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+ value otherwise. */
+ int (*type_dwarf_attribute) (const_tree, int);
+
+ /* Return NULL if TYPE is NOT a C++ pointer to member function type.
+ Otherwise, return the class type when the selector is 0, or the
+ member function type when the selector is 1. */
+ tree (*get_ptrmemfn_type) (const_tree, int);
};
/* Language hooks related to decls and the symbol table. */
--- gcc/langhooks.c.jj 2016-11-01 15:18:44.993506173 +0100
+++ gcc/langhooks.c 2016-11-02 10:07:22.631974425 +0100
@@ -702,6 +702,15 @@ lhd_decl_dwarf_attribute (const_tree, in
return -1;
}
+/* Default implementation of LANG_HOOKS_TYPE_DWARF_ATTRIBUTE. Don't add
+ any attributes. */
+
+int
+lhd_type_dwarf_attribute (const_tree, int)
+{
+ return -1;
+}
+
/* Returns true if the current lang_hooks represents the GNU C frontend. */
bool
--- gcc/langhooks-def.h.jj 2016-11-01 15:18:45.076505123 +0100
+++ gcc/langhooks-def.h 2016-11-02 11:43:14.210522811 +0100
@@ -84,6 +84,7 @@ extern bool lhd_omp_mappable_type (tree)
extern const char *lhd_get_substring_location (const substring_loc &,
location_t *out_loc);
extern int lhd_decl_dwarf_attribute (const_tree, int);
+extern int lhd_type_dwarf_attribute (const_tree, int);
#define LANG_HOOKS_NAME "GNU unknown"
#define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier)
@@ -186,6 +187,8 @@ extern tree lhd_make_node (enum tree_cod
#define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE lhd_enum_underlying_base_type
#define LANG_HOOKS_GET_DEBUG_TYPE NULL
#define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO NULL
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE lhd_type_dwarf_attribute
+#define LANG_HOOKS_GET_PTRMEMFN_TYPE hook_tree_const_tree_int_null
#define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
LANG_HOOKS_MAKE_TYPE, \
@@ -208,7 +211,9 @@ extern tree lhd_make_node (enum tree_cod
LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE, \
LANG_HOOKS_GET_DEBUG_TYPE, \
- LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO \
+ LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
+ LANG_HOOKS_TYPE_DWARF_ATTRIBUTE, \
+ LANG_HOOKS_GET_PTRMEMFN_TYPE \
}
/* Declaration hooks. */
--- gcc/hooks.h.jj 2016-11-01 15:18:44.680510133 +0100
+++ gcc/hooks.h 2016-11-02 11:41:38.491731672 +0100
@@ -89,6 +89,7 @@ extern int hook_int_rtx_mode_as_bool_0 (
bool);
extern tree hook_tree_const_tree_null (const_tree);
+extern tree hook_tree_const_tree_int_null (const_tree, int);
extern tree hook_tree_void_null (void);
extern tree hook_tree_tree_tree_null (tree, tree);
--- gcc/hooks.c.jj 2016-11-01 15:18:44.671510247 +0100
+++ gcc/hooks.c 2016-11-02 11:41:38.490731685 +0100
@@ -429,6 +429,13 @@ hook_tree_const_tree_null (const_tree)
return NULL;
}
+/* Generic hook that takes a const_tree and an int, and returns NULL_TREE. */
+tree
+hook_tree_const_tree_int_null (const_tree, int)
+{
+ return NULL;
+}
+
/* Generic hook that takes no arguments and returns a NULL_TREE. */
tree
hook_tree_void_null (void)
--- gcc/tree.h.jj 2016-11-01 17:54:05.589655658 +0100
+++ gcc/tree.h 2016-11-02 10:08:29.923127967 +0100
@@ -4214,6 +4214,11 @@ extern tree merge_dllimport_decl_attribu
/* Handle a "dllimport" or "dllexport" attribute. */
extern tree handle_dll_attribute (tree *, tree, tree, int, bool *);
+/* Returns true iff CAND and BASE have equivalent language-specific
+ qualifiers. */
+
+extern bool check_lang_type (const_tree cand, const_tree base);
+
/* Returns true iff unqualified CAND and BASE are equivalent. */
extern bool check_base_type (const_tree cand, const_tree base);
--- gcc/tree.c.jj 2016-11-01 15:18:45.185503745 +0100
+++ gcc/tree.c 2016-11-02 10:08:29.921127992 +0100
@@ -6497,6 +6497,21 @@ set_type_quals (tree type, int type_qual
TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
}
+/* Returns true iff CAND and BASE have equivalent language-specific
+ qualifiers. */
+
+bool
+check_lang_type (const_tree cand, const_tree base)
+{
+ if (lang_hooks.types.type_hash_eq == NULL)
+ return true;
+ /* type_hash_eq currently only applies to these types. */
+ if (TREE_CODE (cand) != FUNCTION_TYPE
+ && TREE_CODE (cand) != METHOD_TYPE)
+ return true;
+ return lang_hooks.types.type_hash_eq (cand, base);
+}
+
/* Returns true iff unqualified CAND and BASE are equivalent. */
bool
@@ -6517,7 +6532,8 @@ bool
check_qualified_type (const_tree cand, const_tree base, int type_quals)
{
return (TYPE_QUALS (cand) == type_quals
- && check_base_type (cand, base));
+ && check_base_type (cand, base)
+ && check_lang_type (cand, base));
}
/* Returns true iff CAND is equivalent to BASE with ALIGN. */
@@ -6532,7 +6548,8 @@ check_aligned_type (const_tree cand, con
/* Check alignment. */
&& TYPE_ALIGN (cand) == align
&& attribute_list_equal (TYPE_ATTRIBUTES (cand),
- TYPE_ATTRIBUTES (base)));
+ TYPE_ATTRIBUTES (base))
+ && check_lang_type (cand, base));
}
/* This function checks to see if TYPE matches the size one of the built-in
--- gcc/dwarf2out.c.jj 2016-11-01 23:55:02.870149597 +0100
+++ gcc/dwarf2out.c 2016-11-02 12:36:33.328109864 +0100
@@ -3545,7 +3545,7 @@ static void gen_label_die (tree, dw_die_
static void gen_lexical_block_die (tree, dw_die_ref);
static void gen_inlined_subroutine_die (tree, dw_die_ref);
static void gen_field_die (tree, struct vlr_context *, dw_die_ref);
-static void gen_ptr_to_mbr_type_die (tree, dw_die_ref);
+static void gen_ptr_to_mbr_type_die (tree, dw_die_ref, tree, tree);
static dw_die_ref gen_compile_unit_die (const char *);
static void gen_inheritance_die (tree, tree, tree, dw_die_ref);
static void gen_member_die (tree, dw_die_ref);
@@ -12571,8 +12571,20 @@ modified_type_die (tree type, int cv_qua
copy was created to help us keep track of typedef names) and
that copy might have a different TYPE_UID from the original
..._TYPE node. */
- if (TREE_CODE (type) != VECTOR_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ /* For function/method types, can't just use type_main_variant here,
+ because that can have different ref-qualifiers for C++,
+ but try to canonicalize. */
+ tree main = TYPE_MAIN_VARIANT (type);
+ for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
+ if (check_base_type (t, main) && check_lang_type (t, type))
+ return lookup_type_die (t);
+ return lookup_type_die (type);
+ }
+ else if (TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE)
return lookup_type_die (type_main_variant (type));
else
/* Vectors have the debugging information in the type,
@@ -23105,20 +23117,31 @@ gen_reference_type_die (tree type, dw_di
}
#endif
-/* Generate a DIE for a pointer to a member type. */
+/* Generate a DIE for a pointer to a member type. TYPE can be an
+ OFFSET_TYPE, for a pointer to data member, or a RECORD_TYPE, for a
+ pointer to member function. */
static void
-gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
+gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die,
+ tree class_type, tree member_type)
{
- dw_die_ref ptr_die
- = new_die (DW_TAG_ptr_to_member_type,
- scope_die_for (type, context_die), type);
+ if (lookup_type_die (type))
+ return;
+
+ dw_die_ref 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), TYPE_UNQUALIFIED, false,
+ lookup_type_die (class_type));
+ add_type_attribute (ptr_die, member_type, TYPE_UNQUALIFIED, false,
context_die);
+
+ if (TREE_CODE (type) == OFFSET_TYPE)
+ {
+ dw_loc_descr_ref op = new_loc_descr (DW_OP_plus, 0, 0);
+ add_AT_loc (ptr_die, DW_AT_use_location, op);
+ }
}
static char *producer_string;
@@ -24053,6 +24076,13 @@ gen_subroutine_type_die (tree type, dw_d
if (get_AT (subr_die, DW_AT_name))
add_pubtype (type, subr_die);
+ if ((dwarf_version >= 5 || !dwarf_strict)
+ && lang_hooks.types.type_dwarf_attribute (type, DW_AT_reference) != -1)
+ add_AT_flag (subr_die, DW_AT_reference, 1);
+ if ((dwarf_version >= 5 || !dwarf_strict)
+ && lang_hooks.types.type_dwarf_attribute (type,
+ DW_AT_rvalue_reference) != -1)
+ add_AT_flag (subr_die, DW_AT_rvalue_reference, 1);
}
/* Generate a DIE for a type definition. */
@@ -24278,9 +24308,21 @@ gen_type_die_with_usage (tree type, dw_d
of this type (i.e. without any const or volatile qualifiers) so
get the main variant (i.e. the unqualified version) of this type
now. (Vectors and arrays are special because the debugging info is in the
- cloned type itself). */
- if (TREE_CODE (type) != VECTOR_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)
+ cloned type itself. Similarly function/method types can contain extra
+ ref-qualification). */
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ /* For function/method types, can't use type_main_variant here,
+ because that can have different ref-qualifiers for C++,
+ but try to canonicalize. */
+ tree main = TYPE_MAIN_VARIANT (type);
+ for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
+ if (check_base_type (t, main) && check_lang_type (t, type))
+ type = t;
+ }
+ else if (TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE)
type = type_main_variant (type);
/* If this is an array type with hidden descriptor, handle it first. */
@@ -24331,35 +24373,36 @@ gen_type_die_with_usage (tree type, dw_d
/* For these types, all that is required is that we output a DIE (or a
set of DIEs) to represent the "basis" type. */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_IND_USE);
+ DINFO_USAGE_IND_USE);
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);
+ 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);
+ 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);
+ gen_ptr_to_mbr_type_die (type, context_die,
+ TYPE_OFFSET_BASETYPE (type), TREE_TYPE (type));
break;
case FUNCTION_TYPE:
/* Force out return type (in case it wasn't forced out already). */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_DIR_USE);
+ DINFO_USAGE_DIR_USE);
gen_subroutine_type_die (type, context_die);
break;
case METHOD_TYPE:
/* Force out return type (in case it wasn't forced out already). */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_DIR_USE);
+ DINFO_USAGE_DIR_USE);
gen_subroutine_type_die (type, context_die);
break;
@@ -24368,8 +24411,26 @@ gen_type_die_with_usage (tree type, dw_d
gen_array_type_die (type, context_die);
break;
- case ENUMERAL_TYPE:
case RECORD_TYPE:
+ if (dwarf_version >= 5)
+ {
+ tree class_type = lang_hooks.types.get_ptrmemfn_type (type, 0);
+ if (class_type != NULL_TREE)
+ {
+ gen_type_die_with_usage (class_type, context_die,
+ DINFO_USAGE_IND_USE);
+
+ tree memfn_type = lang_hooks.types.get_ptrmemfn_type (type, 1);
+ gen_type_die_with_usage (memfn_type, context_die,
+ DINFO_USAGE_IND_USE);
+
+ gen_ptr_to_mbr_type_die (type, context_die,
+ class_type, memfn_type);
+ return;
+ }
+ }
+ /* FALLTHROUGH */
+ case ENUMERAL_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
gen_tagged_type_die (type, context_die, usage);
--- gcc/cp/tree.c.jj 2016-11-02 10:00:22.998253014 +0100
+++ gcc/cp/tree.c 2016-11-02 10:08:29.910128131 +0100
@@ -1980,7 +1980,8 @@ static bool
cp_check_qualified_type (const_tree cand, const_tree base, int type_quals,
cp_ref_qualifier rqual, tree raises)
{
- return (check_qualified_type (cand, base, type_quals)
+ return (TYPE_QUALS (cand) == type_quals
+ && check_base_type (cand, base)
&& comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (cand),
ce_exact)
&& type_memfn_rqual (cand) == rqual);
@@ -4080,9 +4081,7 @@ cp_build_type_attribute_variant (tree ty
}
/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
- Called only after doing all language independent checks. Only
- to check TYPE_RAISES_EXCEPTIONS for FUNCTION_TYPE, the rest is already
- compared in type_hash_eq. */
+ Called only after doing all language independent checks. */
bool
cxx_type_hash_eq (const_tree typea, const_tree typeb)
@@ -4090,6 +4089,8 @@ cxx_type_hash_eq (const_tree typea, cons
gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE
|| TREE_CODE (typea) == METHOD_TYPE);
+ if (type_memfn_rqual (typea) != type_memfn_rqual (typeb))
+ return false;
return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea),
TYPE_RAISES_EXCEPTIONS (typeb), ce_exact);
}
--- gcc/cp/cp-objcp-common.c.jj 2016-11-01 19:31:50.386663529 +0100
+++ gcc/cp/cp-objcp-common.c 2016-11-02 11:41:38.482731786 +0100
@@ -131,6 +131,29 @@ cxx_types_compatible_p (tree x, tree y)
return same_type_ignoring_top_level_qualifiers_p (x, y);
}
+/* Return NULL if TYPE is NOT a C++ pointer to member function type.
+ Otherwise, return the class type when the selector is 0, or the
+ member function type when the selector is 1. */
+
+tree
+cp_get_ptrmemfn_type (const_tree type, int selector)
+{
+ if (!TYPE_PTRMEMFUNC_P (type))
+ return NULL_TREE;
+
+ switch (selector)
+ {
+ case 0:
+ return TYPE_PTRMEMFUNC_OBJECT_TYPE (type);
+
+ case 1:
+ return TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type));
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Return -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
value otherwise. */
int
@@ -179,11 +202,6 @@ cp_decl_dwarf_attribute (const_tree decl
&& FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
&& !FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
return 1;
- if ((TREE_CODE (decl) == FUNCTION_TYPE
- || TREE_CODE (decl) == METHOD_TYPE)
- && FUNCTION_REF_QUALIFIED (decl)
- && !FUNCTION_RVALUE_QUALIFIED (decl))
- return 1;
break;
case DW_AT_rvalue_reference:
@@ -192,11 +210,6 @@ cp_decl_dwarf_attribute (const_tree decl
&& FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
&& FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
return 1;
- if ((TREE_CODE (decl) == FUNCTION_TYPE
- || TREE_CODE (decl) == METHOD_TYPE)
- && FUNCTION_REF_QUALIFIED (decl)
- && FUNCTION_RVALUE_QUALIFIED (decl))
- return 1;
break;
case DW_AT_inline:
@@ -210,6 +223,39 @@ cp_decl_dwarf_attribute (const_tree decl
break;
default:
+ break;
+ }
+
+ return -1;
+}
+
+/* Return -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+ value otherwise. */
+int
+cp_type_dwarf_attribute (const_tree type, int attr)
+{
+ if (type == NULL_TREE)
+ return -1;
+
+ switch (attr)
+ {
+ case DW_AT_reference:
+ if ((TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ && FUNCTION_REF_QUALIFIED (type)
+ && !FUNCTION_RVALUE_QUALIFIED (type))
+ return 1;
+ break;
+
+ case DW_AT_rvalue_reference:
+ if ((TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ && FUNCTION_REF_QUALIFIED (type)
+ && FUNCTION_RVALUE_QUALIFIED (type))
+ return 1;
+ break;
+
+ default:
break;
}
--- gcc/cp/cp-objcp-common.h.jj 2016-11-01 15:18:45.148504213 +0100
+++ gcc/cp/cp-objcp-common.h 2016-11-02 11:41:38.483731773 +0100
@@ -21,12 +21,15 @@ along with GCC; see the file COPYING3.
#ifndef GCC_CP_OBJCP_COMMON
#define GCC_CP_OBJCP_COMMON
-/* In cp/cp-lang.c and objcp/objcp-lang.c. */
+/* In cp/objcp-common.c, cp/cp-lang.c and objcp/objcp-lang.c. */
+
+extern tree cp_get_ptrmemfn_type (const_tree, int);
extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
tree, bool);
extern int cp_decl_dwarf_attribute (const_tree, int);
+extern int cp_type_dwarf_attribute (const_tree, int);
extern void cp_common_init_ts (void);
/* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks
@@ -125,12 +128,16 @@ extern void cp_common_init_ts (void);
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
#undef LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE
#define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE cp_reconstruct_complex_type
+#undef LANG_HOOKS_GET_PTRMEMFN_TYPE
+#define LANG_HOOKS_GET_PTRMEMFN_TYPE cp_get_ptrmemfn_type
#undef LANG_HOOKS_TO_TARGET_CHARSET
#define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
#undef LANG_HOOKS_GIMPLIFY_EXPR
#define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
#undef LANG_HOOKS_DECL_DWARF_ATTRIBUTE
#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE cp_decl_dwarf_attribute
+#undef LANG_HOOKS_TYPE_DWARF_ATTRIBUTE
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE cp_type_dwarf_attribute
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
#undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
--- gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C.jj 2016-11-02 11:44:33.141525967 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C 2016-11-02 12:42:56.853276622 +0100
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -gdwarf-5 -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_use_location" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_reference" { xfail { powerpc-ibm-aix* } } } }
+
+struct S;
+typedef int S::*pdm;
+pdm pmf = 0;
--- gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C.jj 2016-11-02 12:37:46.236190858 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C 2016-11-02 12:42:19.524746972 +0100
@@ -0,0 +1,56 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-gdwarf-5 -gno-strict-dwarf -dA" }
+// { dg-final { scan-assembler-times " DW_AT_reference" 5 } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 5 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_subroutine_type" 6 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 7 } }
+// { dg-final { scan-assembler-times " DW_AT_use_location" 1 } }
+
+struct S
+{
+ void foo1 ();
+ void bar1 () &;
+ void baz1 () &&;
+ void foo2 () const;
+ void bar2 () const &;
+ void baz2 () const &&;
+ void foo3 () const;
+ void bar3 () const &;
+ void baz3 () const &&;
+ int d;
+};
+
+void
+test ()
+{
+ S s;
+ auto o1 = &S::foo1;
+ auto r1 = &S::bar1;
+ auto z1 = &S::baz1;
+ auto o2 = &S::foo2;
+ auto r2 = &S::bar2;
+ auto z2 = &S::baz2;
+ auto o3 = &S::foo3;
+ auto r3 = &S::bar3;
+ auto z3 = &S::baz3;
+ auto d1 = &S::d;
+ void (S::*o4) () const;
+ o4 = &S::foo3;
+ void (S::*r4) () const &;
+ r4 = &S::bar3;
+ void (S::*z4) () const &&;
+ z4 = &S::baz3;
+ (s.*o1) ();
+ (s.*r1) ();
+ (S ().*z1) ();
+ (s.*o2) ();
+ (s.*r2) ();
+ (S ().*z2) ();
+ (s.*o3) ();
+ (s.*r3) ();
+ (S ().*z3) ();
+ (s.*o4) ();
+ (s.*r4) ();
+ (S ().*z4) ();
+ s.*d1 = 2;
+}
--- gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C.jj 2016-11-02 11:44:33.141525967 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C 2016-11-02 12:43:07.129147143 +0100
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -gdwarf-5 -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_reference" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_use_location" { xfail { powerpc-ibm-aix* } } } }
+/* It is not clear what if anything we should output for
+ DW_AT_use_location in a pointer to member function, so we don't
+ output it for now. */
+
+struct S {
+ void mf(void) &;
+};
+
+void S::mf() & {}
+
+typedef void (S::*pmft)(void) &;
+pmft pmf = &S::mf;
--- gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C.jj 2016-11-02 11:44:33.141525967 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C 2016-11-02 12:43:15.498041693 +0100
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -gdwarf-5 -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_use_location" { xfail { powerpc-ibm-aix* } } } }
+/* It is not clear what if anything we should output for
+ DW_AT_use_location in a pointer to member function, so we don't
+ output it for now. */
+
+struct S {
+ void mf(void) &&;
+};
+
+void S::mf() && {}
+
+typedef void (S::*pmft)(void) &&;
+pmft pmf = &S::mf;
Jakub
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those
2016-11-02 14:31 [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those Jakub Jelinek
@ 2016-11-02 15:31 ` Jason Merrill
2016-11-02 15:44 ` Jakub Jelinek
0 siblings, 1 reply; 8+ messages in thread
From: Jason Merrill @ 2016-11-02 15:31 UTC (permalink / raw)
To: Jakub Jelinek
Cc: Alexandre Oliva, Keith Seitz, Jan Kratochvil,
Pierre-Marie de Rodat, gcc-patches List
On Wed, Nov 2, 2016 at 10:31 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> It uses Alex' LANG_HOOKS_GET_PTRMEMFN_TYPE langhook. I've tried
> to think about https://gcc.gnu.org/ml/gcc-patches/2011-05/msg00227.html
> and we even have such a langhook now, modified_type_die
> uses lang_hooks.types.get_debug_type, but
> 1) it is just called in modified_type_die and not in
> gen_type_die_with_usage, that looks weird
How much of a problem is that? modified_type_die calls gen_type_die,
does that not cover the cases needed here?
> 2) it is used for something Ada-ish I really don't know how to test etc.
> to be able to find out if it is safe to call it in
> gen_type_die_with_usage too
You could find an Ada test that uses the code and verify that the
output stays the same?
> 3) most importantly, if the C++ version of this langhook would create
> OFFSET_TYPE on the fly, I don't know how to ensure effective sharing
> of DW_TAG_ptr_to_member_type nodes with the same DW_AT_type
> and DW_AT_containing_type; unless the C++ langhook adds some extra
> hash table that caches already created OFFSET_TYPEs or something similar,
> it would create a new OFFSET_TYPE each time it is called
build_offset_type already uses a hash table.
> Also, I really don't know how well does GDB (especially older releases)
> handle DW_TAG_ptr_to_member_type for PMF, so the patch wraps that currently
> with if (dwarf_version >= 5). Quick grep revealed that GDB has code to
> handle the __pfn/__delta fields. So, can I ask somebody from the GDB
> team to test this patch with that if (dwarf_version >= 5) replaced
> with if (1) and see if it works properly with current GDB as well as say
> 4-5 years old one (e.g. with -gdwarf-2 or -gdwarf-3)? If yes, we
> should emit it unconditionally.
This all makes sense to me.
> + if (dwarf_version >= 5)
> + {
> + tree class_type = lang_hooks.types.get_ptrmemfn_type (type, 0);
> + if (class_type != NULL_TREE)
This can be
if (dwarf_version >= 5)
if (tree class_type = lang_hooks.types.get_ptrmemfn_type (type, 0))
Jason
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those
2016-11-02 15:31 ` Jason Merrill
@ 2016-11-02 15:44 ` Jakub Jelinek
2016-11-02 16:33 ` Jakub Jelinek
0 siblings, 1 reply; 8+ messages in thread
From: Jakub Jelinek @ 2016-11-02 15:44 UTC (permalink / raw)
To: Jason Merrill
Cc: Alexandre Oliva, Keith Seitz, Jan Kratochvil,
Pierre-Marie de Rodat, gcc-patches List
On Wed, Nov 02, 2016 at 11:31:25AM -0400, Jason Merrill wrote:
> On Wed, Nov 2, 2016 at 10:31 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> > It uses Alex' LANG_HOOKS_GET_PTRMEMFN_TYPE langhook. I've tried
> > to think about https://gcc.gnu.org/ml/gcc-patches/2011-05/msg00227.html
> > and we even have such a langhook now, modified_type_die
> > uses lang_hooks.types.get_debug_type, but
> > 1) it is just called in modified_type_die and not in
> > gen_type_die_with_usage, that looks weird
>
> How much of a problem is that? modified_type_die calls gen_type_die,
> does that not cover the cases needed here?
If e.g. on the ref-3.C testcase from the patch I put breakpoint on
both gen_ptr_to_mbr_type_die and modified_type_die (the latter only for
type->base.code == RECORD_TYPE), then I see first:
#0 gen_ptr_to_mbr_type_die (type=<record_type 0x7ffff1727150>,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>,
class_type=<record_type 0x7ffff1709540 S>, member_type=<method_type 0x7ffff1709738>) at ../../gcc/dwarf2out.c:23128
#1 0x0000000000c3a7e5 in gen_type_die_with_usage (type=<record_type 0x7ffff1727150>,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>, usage=DINFO_USAGE_DIR_USE)
at ../../gcc/dwarf2out.c:24428
#2 0x0000000000c3ab92 in gen_type_die (type=<record_type 0x7ffff1727150>,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>) at ../../gcc/dwarf2out.c:24491
#3 0x0000000000c3caed in gen_decl_die (decl=<var_decl 0x7ffff7ff9ea0 o1>, origin=<tree 0x0>, ctx=0x0,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>) at ../../gcc/dwarf2out.c:25117
#4 0x0000000000c3b13e in process_scope_var (stmt=<block 0x7ffff17129c0>, decl=<var_decl 0x7ffff7ff9ea0 o1>, origin=<tree 0x0>,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>) at ../../gcc/dwarf2out.c:24620
#5 0x0000000000c3b1bb in decls_for_scope (stmt=<block 0x7ffff17129c0>,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>) at ../../gcc/dwarf2out.c:24645
and only afterwards:
#0 modified_type_die (type=<record_type 0x7ffff1727150>, cv_quals=0, reverse=false,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>) at ../../gcc/dwarf2out.c:12328
#1 0x0000000000c2f03b in add_type_attribute (object_die=<dw_die_ref 0x7ffff1738aa0 DW_TAG_variable <parent=0x7ffff1738910 DW_TAG_subprogram>>,
type=<record_type 0x7ffff1727150>, cv_quals=0, reverse=false,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>) at ../../gcc/dwarf2out.c:20346
#2 0x0000000000c354f4 in gen_variable_die (decl=<var_decl 0x7ffff7ff9ea0 o1>, origin=<tree 0x0>,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>) at ../../gcc/dwarf2out.c:22688
#3 0x0000000000c3cb8e in gen_decl_die (decl=<var_decl 0x7ffff7ff9ea0 o1>, origin=<tree 0x0>, ctx=0x0,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>) at ../../gcc/dwarf2out.c:25138
#4 0x0000000000c3b13e in process_scope_var (stmt=<block 0x7ffff17129c0>, decl=<var_decl 0x7ffff7ff9ea0 o1>, origin=<tree 0x0>,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>) at ../../gcc/dwarf2out.c:24620
#5 0x0000000000c3b1bb in decls_for_scope (stmt=<block 0x7ffff17129c0>,
context_die=<dw_die_ref 0x7ffff1738910 DW_TAG_subprogram <parent=0x7ffff15c7000 DW_TAG_compile_unit>>) at ../../gcc/dwarf2out.c:24645
which means if gen_type_die or gen_type_die_with_usage doesn't
use the langhook, then we'd emit a completely useless { __pfn; __delta }
struct into debug info first, and then in modified_type_die used
the langhook, get OFFSET_TYPE and probably create the
DW_TAG_ptr_to_member_type. So I think we really need that.
> > 2) it is used for something Ada-ish I really don't know how to test etc.
> > to be able to find out if it is safe to call it in
> > gen_type_die_with_usage too
>
> You could find an Ada test that uses the code and verify that the
> output stays the same?
I can try to find the patch that introduced it and if it contained any
testcases.
> > 3) most importantly, if the C++ version of this langhook would create
> > OFFSET_TYPE on the fly, I don't know how to ensure effective sharing
> > of DW_TAG_ptr_to_member_type nodes with the same DW_AT_type
> > and DW_AT_containing_type; unless the C++ langhook adds some extra
> > hash table that caches already created OFFSET_TYPEs or something similar,
> > it would create a new OFFSET_TYPE each time it is called
>
> build_offset_type already uses a hash table.
Ah, ok.
> > Also, I really don't know how well does GDB (especially older releases)
> > handle DW_TAG_ptr_to_member_type for PMF, so the patch wraps that currently
> > with if (dwarf_version >= 5). Quick grep revealed that GDB has code to
> > handle the __pfn/__delta fields. So, can I ask somebody from the GDB
> > team to test this patch with that if (dwarf_version >= 5) replaced
> > with if (1) and see if it works properly with current GDB as well as say
> > 4-5 years old one (e.g. with -gdwarf-2 or -gdwarf-3)? If yes, we
> > should emit it unconditionally.
>
> This all makes sense to me.
>
> > + if (dwarf_version >= 5)
> > + {
> > + tree class_type = lang_hooks.types.get_ptrmemfn_type (type, 0);
> > + if (class_type != NULL_TREE)
>
> This can be
>
> if (dwarf_version >= 5)
> if (tree class_type = lang_hooks.types.get_ptrmemfn_type (type, 0))
Ok.
Jakub
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those
2016-11-02 15:44 ` Jakub Jelinek
@ 2016-11-02 16:33 ` Jakub Jelinek
2016-11-02 17:19 ` Jason Merrill
2016-11-03 17:31 ` [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those Pierre-Marie de Rodat
0 siblings, 2 replies; 8+ messages in thread
From: Jakub Jelinek @ 2016-11-02 16:33 UTC (permalink / raw)
To: Jason Merrill
Cc: Alexandre Oliva, Keith Seitz, Jan Kratochvil,
Pierre-Marie de Rodat, gcc-patches List
On Wed, Nov 02, 2016 at 04:44:05PM +0100, Jakub Jelinek wrote:
> which means if gen_type_die or gen_type_die_with_usage doesn't
> use the langhook, then we'd emit a completely useless { __pfn; __delta }
> struct into debug info first, and then in modified_type_die used
> the langhook, get OFFSET_TYPE and probably create the
> DW_TAG_ptr_to_member_type. So I think we really need that.
>
> > > 2) it is used for something Ada-ish I really don't know how to test etc.
> > > to be able to find out if it is safe to call it in
> > > gen_type_die_with_usage too
> >
> > You could find an Ada test that uses the code and verify that the
> > output stays the same?
>
> I can try to find the patch that introduced it and if it contained any
> testcases.
I couldn't find any unfortunately. Pierre, could you please test if the
following patch doesn't regress anything in the Ada debug info area?
Here is updated patch I'm going to bootstrap/regtest; it generates the
same debuginfo on ref-3.C testcase.
2016-11-02 Jakub Jelinek <jakub@redhat.com>
Alexandre Oliva <aoliva@redhat.com>
Jason Merrill <jason@redhat.com>
PR debug/28767
PR debug/56974
* langhooks.h (struct lang_hooks_for_types): Document type_hash_eq
being also called on METHOD_TYPEs. Add type_dwarf_attribute langhook.
* langhooks.c (lhd_type_dwarf_attribute): New function.
* langhooks-def.h (lhd_type_dwarf_attribute): Declare.
(LANG_HOOKS_TYPE_DWARF_ATTRIBUTE): Define.
(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add
LANG_HOOKS_TYPE_DWARF_ATTRIBUTE.
* tree.h (check_lang_type): Declare.
* tree.c (check_lang_type): New function.
(check_qualified_type, check_aligned_type): Call it.
* dwarf2out.c (modified_type_die): Don't use type_main_variant
for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
check_base_type and check_lang_type.
(gen_ptr_to_mbr_type_die): If lookup_type_die is already non-NULL,
return early. For pointer-to-data-member add DW_AT_use_location
attribute.
(gen_subroutine_type_die): Add DW_AT_{,rvalue_}reference attribute
if needed.
(gen_type_die_with_usage): Don't use type_main_variant
for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
check_base_type and check_lang_type. Formatting fixes. Call
get_debug_type langhook.
cp/
* tree.c (cp_check_qualified_type): Use check_base_type and
TYPE_QUALS comparison instead of check_qualified_type.
(cxx_type_hash_eq): Return false if type_memfn_rqual don't match.
* cp-objcp-common.c (cp_get_debug_type): New function.
(cp_decl_dwarf_attribute): Don't handle types here.
(cp_type_dwarf_attribute): New function.
* cp-objcp-common.h (cp_get_debug_type, cp_type_dwarf_attribute):
Declare.
(LANG_HOOKS_GET_DEBUG_TYPE, LANG_HOOKS_TYPE_DWARF_ATTRIBUTE):
Define.
testsuite/
* g++.dg/debug/dwarf2/ptrdmem-1.C: New test.
* g++.dg/debug/dwarf2/ref-3.C: New test.
* g++.dg/debug/dwarf2/refqual-1.C: New test.
* g++.dg/debug/dwarf2/refqual-2.C: New test.
--- gcc/langhooks.h.jj 2016-11-02 15:55:59.243607249 +0100
+++ gcc/langhooks.h 2016-11-02 17:06:23.818730222 +0100
@@ -120,7 +120,7 @@ struct lang_hooks_for_types
/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
Called only after doing all language independent checks.
At present, this function is only called when both TYPE1 and TYPE2 are
- FUNCTION_TYPEs. */
+ FUNCTION_TYPE or METHOD_TYPE. */
bool (*type_hash_eq) (const_tree, const_tree);
/* Return TRUE if TYPE uses a hidden descriptor and fills in information
@@ -162,6 +162,10 @@ struct lang_hooks_for_types
for the debugger about scale factor, etc. */
bool (*get_fixed_point_type_info) (const_tree,
struct fixed_point_type_info *);
+
+ /* Returns -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+ value otherwise. */
+ int (*type_dwarf_attribute) (const_tree, int);
};
/* Language hooks related to decls and the symbol table. */
--- gcc/langhooks.c.jj 2016-11-02 15:55:59.232607389 +0100
+++ gcc/langhooks.c 2016-11-02 16:35:39.938889496 +0100
@@ -702,6 +702,15 @@ lhd_decl_dwarf_attribute (const_tree, in
return -1;
}
+/* Default implementation of LANG_HOOKS_TYPE_DWARF_ATTRIBUTE. Don't add
+ any attributes. */
+
+int
+lhd_type_dwarf_attribute (const_tree, int)
+{
+ return -1;
+}
+
/* Returns true if the current lang_hooks represents the GNU C frontend. */
bool
--- gcc/langhooks-def.h.jj 2016-11-02 15:55:59.151608423 +0100
+++ gcc/langhooks-def.h 2016-11-02 17:05:54.296095837 +0100
@@ -84,6 +84,7 @@ extern bool lhd_omp_mappable_type (tree)
extern const char *lhd_get_substring_location (const substring_loc &,
location_t *out_loc);
extern int lhd_decl_dwarf_attribute (const_tree, int);
+extern int lhd_type_dwarf_attribute (const_tree, int);
#define LANG_HOOKS_NAME "GNU unknown"
#define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier)
@@ -186,6 +187,7 @@ extern tree lhd_make_node (enum tree_cod
#define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE lhd_enum_underlying_base_type
#define LANG_HOOKS_GET_DEBUG_TYPE NULL
#define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO NULL
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE lhd_type_dwarf_attribute
#define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
LANG_HOOKS_MAKE_TYPE, \
@@ -208,7 +210,8 @@ extern tree lhd_make_node (enum tree_cod
LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE, \
LANG_HOOKS_GET_DEBUG_TYPE, \
- LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO \
+ LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
+ LANG_HOOKS_TYPE_DWARF_ATTRIBUTE \
}
/* Declaration hooks. */
--- gcc/tree.h.jj 2016-11-02 15:55:59.340606010 +0100
+++ gcc/tree.h 2016-11-02 16:35:39.941889458 +0100
@@ -4214,6 +4214,11 @@ extern tree merge_dllimport_decl_attribu
/* Handle a "dllimport" or "dllexport" attribute. */
extern tree handle_dll_attribute (tree *, tree, tree, int, bool *);
+/* Returns true iff CAND and BASE have equivalent language-specific
+ qualifiers. */
+
+extern bool check_lang_type (const_tree cand, const_tree base);
+
/* Returns true iff unqualified CAND and BASE are equivalent. */
extern bool check_base_type (const_tree cand, const_tree base);
--- gcc/tree.c.jj 2016-11-02 15:55:59.322606240 +0100
+++ gcc/tree.c 2016-11-02 16:35:39.945889408 +0100
@@ -6497,6 +6497,21 @@ set_type_quals (tree type, int type_qual
TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
}
+/* Returns true iff CAND and BASE have equivalent language-specific
+ qualifiers. */
+
+bool
+check_lang_type (const_tree cand, const_tree base)
+{
+ if (lang_hooks.types.type_hash_eq == NULL)
+ return true;
+ /* type_hash_eq currently only applies to these types. */
+ if (TREE_CODE (cand) != FUNCTION_TYPE
+ && TREE_CODE (cand) != METHOD_TYPE)
+ return true;
+ return lang_hooks.types.type_hash_eq (cand, base);
+}
+
/* Returns true iff unqualified CAND and BASE are equivalent. */
bool
@@ -6517,7 +6532,8 @@ bool
check_qualified_type (const_tree cand, const_tree base, int type_quals)
{
return (TYPE_QUALS (cand) == type_quals
- && check_base_type (cand, base));
+ && check_base_type (cand, base)
+ && check_lang_type (cand, base));
}
/* Returns true iff CAND is equivalent to BASE with ALIGN. */
@@ -6532,7 +6548,8 @@ check_aligned_type (const_tree cand, con
/* Check alignment. */
&& TYPE_ALIGN (cand) == align
&& attribute_list_equal (TYPE_ATTRIBUTES (cand),
- TYPE_ATTRIBUTES (base)));
+ TYPE_ATTRIBUTES (base))
+ && check_lang_type (cand, base));
}
/* This function checks to see if TYPE matches the size one of the built-in
--- gcc/dwarf2out.c.jj 2016-11-02 15:55:59.185607989 +0100
+++ gcc/dwarf2out.c 2016-11-02 17:13:44.522272451 +0100
@@ -12571,8 +12571,20 @@ modified_type_die (tree type, int cv_qua
copy was created to help us keep track of typedef names) and
that copy might have a different TYPE_UID from the original
..._TYPE node. */
- if (TREE_CODE (type) != VECTOR_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ /* For function/method types, can't just use type_main_variant here,
+ because that can have different ref-qualifiers for C++,
+ but try to canonicalize. */
+ tree main = TYPE_MAIN_VARIANT (type);
+ for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
+ if (check_base_type (t, main) && check_lang_type (t, type))
+ return lookup_type_die (t);
+ return lookup_type_die (type);
+ }
+ else if (TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE)
return lookup_type_die (type_main_variant (type));
else
/* Vectors have the debugging information in the type,
@@ -23105,20 +23117,31 @@ gen_reference_type_die (tree type, dw_di
}
#endif
-/* Generate a DIE for a pointer to a member type. */
+/* Generate a DIE for a pointer to a member type. TYPE can be an
+ OFFSET_TYPE, for a pointer to data member, or a RECORD_TYPE, for a
+ pointer to member function. */
static void
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);
+ if (lookup_type_die (type))
+ return;
+
+ dw_die_ref 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), TYPE_UNQUALIFIED, false,
context_die);
+
+ if (TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE
+ && TREE_CODE (TREE_TYPE (type)) != METHOD_TYPE)
+ {
+ dw_loc_descr_ref op = new_loc_descr (DW_OP_plus, 0, 0);
+ add_AT_loc (ptr_die, DW_AT_use_location, op);
+ }
}
static char *producer_string;
@@ -24053,6 +24076,13 @@ gen_subroutine_type_die (tree type, dw_d
if (get_AT (subr_die, DW_AT_name))
add_pubtype (type, subr_die);
+ if ((dwarf_version >= 5 || !dwarf_strict)
+ && lang_hooks.types.type_dwarf_attribute (type, DW_AT_reference) != -1)
+ add_AT_flag (subr_die, DW_AT_reference, 1);
+ if ((dwarf_version >= 5 || !dwarf_strict)
+ && lang_hooks.types.type_dwarf_attribute (type,
+ DW_AT_rvalue_reference) != -1)
+ add_AT_flag (subr_die, DW_AT_rvalue_reference, 1);
}
/* Generate a DIE for a type definition. */
@@ -24274,13 +24304,36 @@ gen_type_die_with_usage (tree type, dw_d
return;
}
+ if (lang_hooks.types.get_debug_type)
+ {
+ tree debug_type = lang_hooks.types.get_debug_type (type);
+
+ if (debug_type != NULL_TREE && debug_type != type)
+ {
+ gen_type_die_with_usage (debug_type, context_die, usage);
+ 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
now. (Vectors and arrays are special because the debugging info is in the
- cloned type itself). */
- if (TREE_CODE (type) != VECTOR_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)
+ cloned type itself. Similarly function/method types can contain extra
+ ref-qualification). */
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ /* For function/method types, can't use type_main_variant here,
+ because that can have different ref-qualifiers for C++,
+ but try to canonicalize. */
+ tree main = TYPE_MAIN_VARIANT (type);
+ for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
+ if (check_base_type (t, main) && check_lang_type (t, type))
+ type = t;
+ }
+ else if (TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE)
type = type_main_variant (type);
/* If this is an array type with hidden descriptor, handle it first. */
@@ -24331,18 +24384,18 @@ gen_type_die_with_usage (tree type, dw_d
/* For these types, all that is required is that we output a DIE (or a
set of DIEs) to represent the "basis" type. */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_IND_USE);
+ DINFO_USAGE_IND_USE);
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);
+ 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);
+ DINFO_USAGE_IND_USE);
/* Now output a DIE to represent this pointer-to-data-member type
itself. */
@@ -24352,14 +24405,14 @@ gen_type_die_with_usage (tree type, dw_d
case FUNCTION_TYPE:
/* Force out return type (in case it wasn't forced out already). */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_DIR_USE);
+ DINFO_USAGE_DIR_USE);
gen_subroutine_type_die (type, context_die);
break;
case METHOD_TYPE:
/* Force out return type (in case it wasn't forced out already). */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_DIR_USE);
+ DINFO_USAGE_DIR_USE);
gen_subroutine_type_die (type, context_die);
break;
--- gcc/cp/tree.c.jj 2016-11-02 15:55:59.186607976 +0100
+++ gcc/cp/tree.c 2016-11-02 16:35:39.953889307 +0100
@@ -1980,7 +1980,8 @@ static bool
cp_check_qualified_type (const_tree cand, const_tree base, int type_quals,
cp_ref_qualifier rqual, tree raises)
{
- return (check_qualified_type (cand, base, type_quals)
+ return (TYPE_QUALS (cand) == type_quals
+ && check_base_type (cand, base)
&& comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (cand),
ce_exact)
&& type_memfn_rqual (cand) == rqual);
@@ -4080,9 +4081,7 @@ cp_build_type_attribute_variant (tree ty
}
/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
- Called only after doing all language independent checks. Only
- to check TYPE_RAISES_EXCEPTIONS for FUNCTION_TYPE, the rest is already
- compared in type_hash_eq. */
+ Called only after doing all language independent checks. */
bool
cxx_type_hash_eq (const_tree typea, const_tree typeb)
@@ -4090,6 +4089,8 @@ cxx_type_hash_eq (const_tree typea, cons
gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE
|| TREE_CODE (typea) == METHOD_TYPE);
+ if (type_memfn_rqual (typea) != type_memfn_rqual (typeb))
+ return false;
return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea),
TYPE_RAISES_EXCEPTIONS (typeb), ce_exact);
}
--- gcc/cp/cp-objcp-common.c.jj 2016-11-02 15:55:59.205607734 +0100
+++ gcc/cp/cp-objcp-common.c 2016-11-02 17:18:50.607481823 +0100
@@ -131,6 +131,19 @@ cxx_types_compatible_p (tree x, tree y)
return same_type_ignoring_top_level_qualifiers_p (x, y);
}
+/* Return a type to use in the debug info instead of TYPE, or NULL_TREE to
+ keep TYPE. */
+
+tree
+cp_get_debug_type (const_tree type)
+{
+ if (TYPE_PTRMEMFUNC_P (type) && dwarf_version >= 5)
+ return build_offset_type (TYPE_PTRMEMFUNC_OBJECT_TYPE (type),
+ TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)));
+
+ return NULL_TREE;
+}
+
/* Return -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
value otherwise. */
int
@@ -179,11 +192,6 @@ cp_decl_dwarf_attribute (const_tree decl
&& FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
&& !FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
return 1;
- if ((TREE_CODE (decl) == FUNCTION_TYPE
- || TREE_CODE (decl) == METHOD_TYPE)
- && FUNCTION_REF_QUALIFIED (decl)
- && !FUNCTION_RVALUE_QUALIFIED (decl))
- return 1;
break;
case DW_AT_rvalue_reference:
@@ -192,11 +200,6 @@ cp_decl_dwarf_attribute (const_tree decl
&& FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
&& FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
return 1;
- if ((TREE_CODE (decl) == FUNCTION_TYPE
- || TREE_CODE (decl) == METHOD_TYPE)
- && FUNCTION_REF_QUALIFIED (decl)
- && FUNCTION_RVALUE_QUALIFIED (decl))
- return 1;
break;
case DW_AT_inline:
@@ -210,6 +213,39 @@ cp_decl_dwarf_attribute (const_tree decl
break;
default:
+ break;
+ }
+
+ return -1;
+}
+
+/* Return -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+ value otherwise. */
+int
+cp_type_dwarf_attribute (const_tree type, int attr)
+{
+ if (type == NULL_TREE)
+ return -1;
+
+ switch (attr)
+ {
+ case DW_AT_reference:
+ if ((TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ && FUNCTION_REF_QUALIFIED (type)
+ && !FUNCTION_RVALUE_QUALIFIED (type))
+ return 1;
+ break;
+
+ case DW_AT_rvalue_reference:
+ if ((TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ && FUNCTION_REF_QUALIFIED (type)
+ && FUNCTION_RVALUE_QUALIFIED (type))
+ return 1;
+ break;
+
+ default:
break;
}
--- gcc/cp/cp-objcp-common.h.jj 2016-11-02 15:55:59.218607568 +0100
+++ gcc/cp/cp-objcp-common.h 2016-11-02 17:19:30.183991698 +0100
@@ -21,12 +21,14 @@ along with GCC; see the file COPYING3.
#ifndef GCC_CP_OBJCP_COMMON
#define GCC_CP_OBJCP_COMMON
-/* In cp/cp-lang.c and objcp/objcp-lang.c. */
+/* In cp/objcp-common.c, cp/cp-lang.c and objcp/objcp-lang.c. */
+extern tree cp_get_debug_type (const_tree);
extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
tree, bool);
extern int cp_decl_dwarf_attribute (const_tree, int);
+extern int cp_type_dwarf_attribute (const_tree, int);
extern void cp_common_init_ts (void);
/* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks
@@ -125,12 +127,16 @@ extern void cp_common_init_ts (void);
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
#undef LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE
#define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE cp_reconstruct_complex_type
+#undef LANG_HOOKS_GET_DEBUG_TYPE
+#define LANG_HOOKS_GET_DEBUG_TYPE cp_get_debug_type
#undef LANG_HOOKS_TO_TARGET_CHARSET
#define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
#undef LANG_HOOKS_GIMPLIFY_EXPR
#define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
#undef LANG_HOOKS_DECL_DWARF_ATTRIBUTE
#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE cp_decl_dwarf_attribute
+#undef LANG_HOOKS_TYPE_DWARF_ATTRIBUTE
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE cp_type_dwarf_attribute
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
#undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
--- gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C.jj 2016-11-02 16:35:39.954889295 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C 2016-11-02 16:35:39.954889295 +0100
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -gdwarf-5 -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_use_location" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_reference" { xfail { powerpc-ibm-aix* } } } }
+
+struct S;
+typedef int S::*pdm;
+pdm pmf = 0;
--- gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C.jj 2016-11-02 16:35:39.954889295 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C 2016-11-02 16:35:39.954889295 +0100
@@ -0,0 +1,56 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-gdwarf-5 -gno-strict-dwarf -dA" }
+// { dg-final { scan-assembler-times " DW_AT_reference" 5 } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 5 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_subroutine_type" 6 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 7 } }
+// { dg-final { scan-assembler-times " DW_AT_use_location" 1 } }
+
+struct S
+{
+ void foo1 ();
+ void bar1 () &;
+ void baz1 () &&;
+ void foo2 () const;
+ void bar2 () const &;
+ void baz2 () const &&;
+ void foo3 () const;
+ void bar3 () const &;
+ void baz3 () const &&;
+ int d;
+};
+
+void
+test ()
+{
+ S s;
+ auto o1 = &S::foo1;
+ auto r1 = &S::bar1;
+ auto z1 = &S::baz1;
+ auto o2 = &S::foo2;
+ auto r2 = &S::bar2;
+ auto z2 = &S::baz2;
+ auto o3 = &S::foo3;
+ auto r3 = &S::bar3;
+ auto z3 = &S::baz3;
+ auto d1 = &S::d;
+ void (S::*o4) () const;
+ o4 = &S::foo3;
+ void (S::*r4) () const &;
+ r4 = &S::bar3;
+ void (S::*z4) () const &&;
+ z4 = &S::baz3;
+ (s.*o1) ();
+ (s.*r1) ();
+ (S ().*z1) ();
+ (s.*o2) ();
+ (s.*r2) ();
+ (S ().*z2) ();
+ (s.*o3) ();
+ (s.*r3) ();
+ (S ().*z3) ();
+ (s.*o4) ();
+ (s.*r4) ();
+ (S ().*z4) ();
+ s.*d1 = 2;
+}
--- gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C.jj 2016-11-02 16:35:39.954889295 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C 2016-11-02 16:35:39.954889295 +0100
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -gdwarf-5 -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_reference" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_use_location" { xfail { powerpc-ibm-aix* } } } }
+/* It is not clear what if anything we should output for
+ DW_AT_use_location in a pointer to member function, so we don't
+ output it for now. */
+
+struct S {
+ void mf(void) &;
+};
+
+void S::mf() & {}
+
+typedef void (S::*pmft)(void) &;
+pmft pmf = &S::mf;
--- gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C.jj 2016-11-02 16:35:39.955889282 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C 2016-11-02 16:35:39.955889282 +0100
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -gdwarf-5 -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_use_location" { xfail { powerpc-ibm-aix* } } } }
+/* It is not clear what if anything we should output for
+ DW_AT_use_location in a pointer to member function, so we don't
+ output it for now. */
+
+struct S {
+ void mf(void) &&;
+};
+
+void S::mf() && {}
+
+typedef void (S::*pmft)(void) &&;
+pmft pmf = &S::mf;
Jakub
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those
2016-11-02 16:33 ` Jakub Jelinek
@ 2016-11-02 17:19 ` Jason Merrill
2016-11-03 16:39 ` [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those (take 2) Jakub Jelinek
2016-11-03 17:31 ` [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those Pierre-Marie de Rodat
1 sibling, 1 reply; 8+ messages in thread
From: Jason Merrill @ 2016-11-02 17:19 UTC (permalink / raw)
To: Jakub Jelinek
Cc: Alexandre Oliva, Keith Seitz, Jan Kratochvil,
Pierre-Marie de Rodat, gcc-patches List
On Wed, Nov 2, 2016 at 12:33 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Nov 02, 2016 at 04:44:05PM +0100, Jakub Jelinek wrote:
>> which means if gen_type_die or gen_type_die_with_usage doesn't
>> use the langhook, then we'd emit a completely useless { __pfn; __delta }
>> struct into debug info first, and then in modified_type_die used
>> the langhook, get OFFSET_TYPE and probably create the
>> DW_TAG_ptr_to_member_type. So I think we really need that.
>>
>> > > 2) it is used for something Ada-ish I really don't know how to test etc.
>> > > to be able to find out if it is safe to call it in
>> > > gen_type_die_with_usage too
>> >
>> > You could find an Ada test that uses the code and verify that the
>> > output stays the same?
>>
>> I can try to find the patch that introduced it and if it contained any
>> testcases.
>
> I couldn't find any unfortunately. Pierre, could you please test if the
> following patch doesn't regress anything in the Ada debug info area?
>
> Here is updated patch I'm going to bootstrap/regtest; it generates the
> same debuginfo on ref-3.C testcase.
Looks good.
Jason
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those (take 2)
2016-11-02 17:19 ` Jason Merrill
@ 2016-11-03 16:39 ` Jakub Jelinek
2016-11-03 19:54 ` Jason Merrill
0 siblings, 1 reply; 8+ messages in thread
From: Jakub Jelinek @ 2016-11-03 16:39 UTC (permalink / raw)
To: Jason Merrill
Cc: Alexandre Oliva, Keith Seitz, Jan Kratochvil,
Pierre-Marie de Rodat, gcc-patches List
On Wed, Nov 02, 2016 at 01:19:09PM -0400, Jason Merrill wrote:
> On Wed, Nov 2, 2016 at 12:33 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> > On Wed, Nov 02, 2016 at 04:44:05PM +0100, Jakub Jelinek wrote:
> >> which means if gen_type_die or gen_type_die_with_usage doesn't
> >> use the langhook, then we'd emit a completely useless { __pfn; __delta }
> >> struct into debug info first, and then in modified_type_die used
> >> the langhook, get OFFSET_TYPE and probably create the
> >> DW_TAG_ptr_to_member_type. So I think we really need that.
> >>
> >> > > 2) it is used for something Ada-ish I really don't know how to test etc.
> >> > > to be able to find out if it is safe to call it in
> >> > > gen_type_die_with_usage too
> >> >
> >> > You could find an Ada test that uses the code and verify that the
> >> > output stays the same?
> >>
> >> I can try to find the patch that introduced it and if it contained any
> >> testcases.
> >
> > I couldn't find any unfortunately. Pierre, could you please test if the
> > following patch doesn't regress anything in the Ada debug info area?
> >
> > Here is updated patch I'm going to bootstrap/regtest; it generates the
> > same debuginfo on ref-3.C testcase.
>
> Looks good.
Keith's testing revealed a bug in the patch, that we don't emit
DW_TAG_typedef for PMF typedefs. Fixed by adding && !typedef_variant_p (type)
check to the cp_get_debug_type hook, so that we emit the proper typedef
with the right name and only its DECL_ORIGINAL_TYPE is replaced with
OFFSET_TYPE handling. I believe that was the only issue, so I think it
should be ok to enable it always, not just for -gdwarf-5.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2016-11-03 Jakub Jelinek <jakub@redhat.com>
Alexandre Oliva <aoliva@redhat.com>
Jason Merrill <jason@redhat.com>
PR debug/28767
PR debug/56974
* langhooks.h (struct lang_hooks_for_types): Document type_hash_eq
being also called on METHOD_TYPEs. Add type_dwarf_attribute langhook.
* langhooks.c (lhd_type_dwarf_attribute): New function.
* langhooks-def.h (lhd_type_dwarf_attribute): Declare.
(LANG_HOOKS_TYPE_DWARF_ATTRIBUTE): Define.
(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add
LANG_HOOKS_TYPE_DWARF_ATTRIBUTE.
* tree.h (check_lang_type): Declare.
* tree.c (check_lang_type): New function.
(check_qualified_type, check_aligned_type): Call it.
* dwarf2out.c (modified_type_die): Don't use type_main_variant
for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
check_base_type and check_lang_type.
(gen_ptr_to_mbr_type_die): If lookup_type_die is already non-NULL,
return early. For pointer-to-data-member add DW_AT_use_location
attribute.
(gen_subroutine_type_die): Add DW_AT_{,rvalue_}reference attribute
if needed.
(gen_type_die_with_usage): Don't use type_main_variant
for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
check_base_type and check_lang_type. Formatting fixes. Call
get_debug_type langhook.
cp/
* tree.c (cp_check_qualified_type): Use check_base_type and
TYPE_QUALS comparison instead of check_qualified_type.
(cxx_type_hash_eq): Return false if type_memfn_rqual don't match.
* cp-objcp-common.c (cp_get_debug_type): New function.
(cp_decl_dwarf_attribute): Don't handle types here.
(cp_type_dwarf_attribute): New function.
* cp-objcp-common.h (cp_get_debug_type, cp_type_dwarf_attribute):
Declare.
(LANG_HOOKS_GET_DEBUG_TYPE, LANG_HOOKS_TYPE_DWARF_ATTRIBUTE):
Define.
testsuite/
* g++.dg/debug/dwarf2/ptrdmem-1.C: New test.
* g++.dg/debug/dwarf2/ref-3.C: New test.
* g++.dg/debug/dwarf2/ref-4.C: New test.
* g++.dg/debug/dwarf2/refqual-1.C: New test.
* g++.dg/debug/dwarf2/refqual-2.C: New test.
--- gcc/langhooks.h.jj 2016-11-03 08:47:59.373747992 +0100
+++ gcc/langhooks.h 2016-11-03 13:08:27.003538880 +0100
@@ -120,7 +120,7 @@ struct lang_hooks_for_types
/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
Called only after doing all language independent checks.
At present, this function is only called when both TYPE1 and TYPE2 are
- FUNCTION_TYPEs. */
+ FUNCTION_TYPE or METHOD_TYPE. */
bool (*type_hash_eq) (const_tree, const_tree);
/* Return TRUE if TYPE uses a hidden descriptor and fills in information
@@ -162,6 +162,10 @@ struct lang_hooks_for_types
for the debugger about scale factor, etc. */
bool (*get_fixed_point_type_info) (const_tree,
struct fixed_point_type_info *);
+
+ /* Returns -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+ value otherwise. */
+ int (*type_dwarf_attribute) (const_tree, int);
};
/* Language hooks related to decls and the symbol table. */
--- gcc/langhooks.c.jj 2016-11-03 08:47:59.367748069 +0100
+++ gcc/langhooks.c 2016-11-03 13:08:27.003538880 +0100
@@ -702,6 +702,15 @@ lhd_decl_dwarf_attribute (const_tree, in
return -1;
}
+/* Default implementation of LANG_HOOKS_TYPE_DWARF_ATTRIBUTE. Don't add
+ any attributes. */
+
+int
+lhd_type_dwarf_attribute (const_tree, int)
+{
+ return -1;
+}
+
/* Returns true if the current lang_hooks represents the GNU C frontend. */
bool
--- gcc/langhooks-def.h.jj 2016-11-03 08:47:59.143750935 +0100
+++ gcc/langhooks-def.h 2016-11-03 13:08:27.003538880 +0100
@@ -84,6 +84,7 @@ extern bool lhd_omp_mappable_type (tree)
extern const char *lhd_get_substring_location (const substring_loc &,
location_t *out_loc);
extern int lhd_decl_dwarf_attribute (const_tree, int);
+extern int lhd_type_dwarf_attribute (const_tree, int);
#define LANG_HOOKS_NAME "GNU unknown"
#define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier)
@@ -186,6 +187,7 @@ extern tree lhd_make_node (enum tree_cod
#define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE lhd_enum_underlying_base_type
#define LANG_HOOKS_GET_DEBUG_TYPE NULL
#define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO NULL
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE lhd_type_dwarf_attribute
#define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
LANG_HOOKS_MAKE_TYPE, \
@@ -208,7 +210,8 @@ extern tree lhd_make_node (enum tree_cod
LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE, \
LANG_HOOKS_GET_DEBUG_TYPE, \
- LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO \
+ LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
+ LANG_HOOKS_TYPE_DWARF_ATTRIBUTE \
}
/* Declaration hooks. */
--- gcc/tree.h.jj 2016-11-03 08:47:59.104751435 +0100
+++ gcc/tree.h 2016-11-03 13:08:27.005538855 +0100
@@ -4214,6 +4214,11 @@ extern tree merge_dllimport_decl_attribu
/* Handle a "dllimport" or "dllexport" attribute. */
extern tree handle_dll_attribute (tree *, tree, tree, int, bool *);
+/* Returns true iff CAND and BASE have equivalent language-specific
+ qualifiers. */
+
+extern bool check_lang_type (const_tree cand, const_tree base);
+
/* Returns true iff unqualified CAND and BASE are equivalent. */
extern bool check_base_type (const_tree cand, const_tree base);
--- gcc/tree.c.jj 2016-11-03 08:47:59.091751601 +0100
+++ gcc/tree.c 2016-11-03 13:08:27.009538805 +0100
@@ -6497,6 +6497,21 @@ set_type_quals (tree type, int type_qual
TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
}
+/* Returns true iff CAND and BASE have equivalent language-specific
+ qualifiers. */
+
+bool
+check_lang_type (const_tree cand, const_tree base)
+{
+ if (lang_hooks.types.type_hash_eq == NULL)
+ return true;
+ /* type_hash_eq currently only applies to these types. */
+ if (TREE_CODE (cand) != FUNCTION_TYPE
+ && TREE_CODE (cand) != METHOD_TYPE)
+ return true;
+ return lang_hooks.types.type_hash_eq (cand, base);
+}
+
/* Returns true iff unqualified CAND and BASE are equivalent. */
bool
@@ -6517,7 +6532,8 @@ bool
check_qualified_type (const_tree cand, const_tree base, int type_quals)
{
return (TYPE_QUALS (cand) == type_quals
- && check_base_type (cand, base));
+ && check_base_type (cand, base)
+ && check_lang_type (cand, base));
}
/* Returns true iff CAND is equivalent to BASE with ALIGN. */
@@ -6532,7 +6548,8 @@ check_aligned_type (const_tree cand, con
/* Check alignment. */
&& TYPE_ALIGN (cand) == align
&& attribute_list_equal (TYPE_ATTRIBUTES (cand),
- TYPE_ATTRIBUTES (base)));
+ TYPE_ATTRIBUTES (base))
+ && check_lang_type (cand, base));
}
/* This function checks to see if TYPE matches the size one of the built-in
--- gcc/dwarf2out.c.jj 2016-11-03 12:26:03.192459170 +0100
+++ gcc/dwarf2out.c 2016-11-03 13:08:27.015538730 +0100
@@ -12591,8 +12591,20 @@ modified_type_die (tree type, int cv_qua
copy was created to help us keep track of typedef names) and
that copy might have a different TYPE_UID from the original
..._TYPE node. */
- if (TREE_CODE (type) != VECTOR_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ /* For function/method types, can't just use type_main_variant here,
+ because that can have different ref-qualifiers for C++,
+ but try to canonicalize. */
+ tree main = TYPE_MAIN_VARIANT (type);
+ for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
+ if (check_base_type (t, main) && check_lang_type (t, type))
+ return lookup_type_die (t);
+ return lookup_type_die (type);
+ }
+ else if (TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE)
return lookup_type_die (type_main_variant (type));
else
/* Vectors have the debugging information in the type,
@@ -23125,20 +23137,31 @@ gen_reference_type_die (tree type, dw_di
}
#endif
-/* Generate a DIE for a pointer to a member type. */
+/* Generate a DIE for a pointer to a member type. TYPE can be an
+ OFFSET_TYPE, for a pointer to data member, or a RECORD_TYPE, for a
+ pointer to member function. */
static void
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);
+ if (lookup_type_die (type))
+ return;
+
+ dw_die_ref 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), TYPE_UNQUALIFIED, false,
context_die);
+
+ if (TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE
+ && TREE_CODE (TREE_TYPE (type)) != METHOD_TYPE)
+ {
+ dw_loc_descr_ref op = new_loc_descr (DW_OP_plus, 0, 0);
+ add_AT_loc (ptr_die, DW_AT_use_location, op);
+ }
}
static char *producer_string;
@@ -24073,6 +24096,13 @@ gen_subroutine_type_die (tree type, dw_d
if (get_AT (subr_die, DW_AT_name))
add_pubtype (type, subr_die);
+ if ((dwarf_version >= 5 || !dwarf_strict)
+ && lang_hooks.types.type_dwarf_attribute (type, DW_AT_reference) != -1)
+ add_AT_flag (subr_die, DW_AT_reference, 1);
+ if ((dwarf_version >= 5 || !dwarf_strict)
+ && lang_hooks.types.type_dwarf_attribute (type,
+ DW_AT_rvalue_reference) != -1)
+ add_AT_flag (subr_die, DW_AT_rvalue_reference, 1);
}
/* Generate a DIE for a type definition. */
@@ -24294,13 +24324,36 @@ gen_type_die_with_usage (tree type, dw_d
return;
}
+ if (lang_hooks.types.get_debug_type)
+ {
+ tree debug_type = lang_hooks.types.get_debug_type (type);
+
+ if (debug_type != NULL_TREE && debug_type != type)
+ {
+ gen_type_die_with_usage (debug_type, context_die, usage);
+ 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
now. (Vectors and arrays are special because the debugging info is in the
- cloned type itself). */
- if (TREE_CODE (type) != VECTOR_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)
+ cloned type itself. Similarly function/method types can contain extra
+ ref-qualification). */
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ /* For function/method types, can't use type_main_variant here,
+ because that can have different ref-qualifiers for C++,
+ but try to canonicalize. */
+ tree main = TYPE_MAIN_VARIANT (type);
+ for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
+ if (check_base_type (t, main) && check_lang_type (t, type))
+ type = t;
+ }
+ else if (TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE)
type = type_main_variant (type);
/* If this is an array type with hidden descriptor, handle it first. */
@@ -24351,18 +24404,18 @@ gen_type_die_with_usage (tree type, dw_d
/* For these types, all that is required is that we output a DIE (or a
set of DIEs) to represent the "basis" type. */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_IND_USE);
+ DINFO_USAGE_IND_USE);
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);
+ 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);
+ DINFO_USAGE_IND_USE);
/* Now output a DIE to represent this pointer-to-data-member type
itself. */
@@ -24372,14 +24425,14 @@ gen_type_die_with_usage (tree type, dw_d
case FUNCTION_TYPE:
/* Force out return type (in case it wasn't forced out already). */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_DIR_USE);
+ DINFO_USAGE_DIR_USE);
gen_subroutine_type_die (type, context_die);
break;
case METHOD_TYPE:
/* Force out return type (in case it wasn't forced out already). */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_DIR_USE);
+ DINFO_USAGE_DIR_USE);
gen_subroutine_type_die (type, context_die);
break;
--- gcc/cp/tree.c.jj 2016-11-03 08:47:59.217749988 +0100
+++ gcc/cp/tree.c 2016-11-03 13:08:27.017538705 +0100
@@ -1980,7 +1980,8 @@ static bool
cp_check_qualified_type (const_tree cand, const_tree base, int type_quals,
cp_ref_qualifier rqual, tree raises)
{
- return (check_qualified_type (cand, base, type_quals)
+ return (TYPE_QUALS (cand) == type_quals
+ && check_base_type (cand, base)
&& comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (cand),
ce_exact)
&& type_memfn_rqual (cand) == rqual);
@@ -4080,9 +4081,7 @@ cp_build_type_attribute_variant (tree ty
}
/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
- Called only after doing all language independent checks. Only
- to check TYPE_RAISES_EXCEPTIONS for FUNCTION_TYPE, the rest is already
- compared in type_hash_eq. */
+ Called only after doing all language independent checks. */
bool
cxx_type_hash_eq (const_tree typea, const_tree typeb)
@@ -4090,6 +4089,8 @@ cxx_type_hash_eq (const_tree typea, cons
gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE
|| TREE_CODE (typea) == METHOD_TYPE);
+ if (type_memfn_rqual (typea) != type_memfn_rqual (typeb))
+ return false;
return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea),
TYPE_RAISES_EXCEPTIONS (typeb), ce_exact);
}
--- gcc/cp/cp-objcp-common.c.jj 2016-11-03 08:47:59.225749886 +0100
+++ gcc/cp/cp-objcp-common.c 2016-11-03 13:08:27.017538705 +0100
@@ -131,6 +131,19 @@ cxx_types_compatible_p (tree x, tree y)
return same_type_ignoring_top_level_qualifiers_p (x, y);
}
+/* Return a type to use in the debug info instead of TYPE, or NULL_TREE to
+ keep TYPE. */
+
+tree
+cp_get_debug_type (const_tree type)
+{
+ if (TYPE_PTRMEMFUNC_P (type) && !typedef_variant_p (type))
+ return build_offset_type (TYPE_PTRMEMFUNC_OBJECT_TYPE (type),
+ TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)));
+
+ return NULL_TREE;
+}
+
/* Return -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
value otherwise. */
int
@@ -179,11 +192,6 @@ cp_decl_dwarf_attribute (const_tree decl
&& FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
&& !FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
return 1;
- if ((TREE_CODE (decl) == FUNCTION_TYPE
- || TREE_CODE (decl) == METHOD_TYPE)
- && FUNCTION_REF_QUALIFIED (decl)
- && !FUNCTION_RVALUE_QUALIFIED (decl))
- return 1;
break;
case DW_AT_rvalue_reference:
@@ -192,11 +200,6 @@ cp_decl_dwarf_attribute (const_tree decl
&& FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
&& FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
return 1;
- if ((TREE_CODE (decl) == FUNCTION_TYPE
- || TREE_CODE (decl) == METHOD_TYPE)
- && FUNCTION_REF_QUALIFIED (decl)
- && FUNCTION_RVALUE_QUALIFIED (decl))
- return 1;
break;
case DW_AT_inline:
@@ -210,6 +213,39 @@ cp_decl_dwarf_attribute (const_tree decl
break;
default:
+ break;
+ }
+
+ return -1;
+}
+
+/* Return -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+ value otherwise. */
+int
+cp_type_dwarf_attribute (const_tree type, int attr)
+{
+ if (type == NULL_TREE)
+ return -1;
+
+ switch (attr)
+ {
+ case DW_AT_reference:
+ if ((TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ && FUNCTION_REF_QUALIFIED (type)
+ && !FUNCTION_RVALUE_QUALIFIED (type))
+ return 1;
+ break;
+
+ case DW_AT_rvalue_reference:
+ if ((TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ && FUNCTION_REF_QUALIFIED (type)
+ && FUNCTION_RVALUE_QUALIFIED (type))
+ return 1;
+ break;
+
+ default:
break;
}
--- gcc/cp/cp-objcp-common.h.jj 2016-11-03 08:47:59.193750296 +0100
+++ gcc/cp/cp-objcp-common.h 2016-11-03 13:08:27.017538705 +0100
@@ -21,12 +21,14 @@ along with GCC; see the file COPYING3.
#ifndef GCC_CP_OBJCP_COMMON
#define GCC_CP_OBJCP_COMMON
-/* In cp/cp-lang.c and objcp/objcp-lang.c. */
+/* In cp/objcp-common.c, cp/cp-lang.c and objcp/objcp-lang.c. */
+extern tree cp_get_debug_type (const_tree);
extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
tree, bool);
extern int cp_decl_dwarf_attribute (const_tree, int);
+extern int cp_type_dwarf_attribute (const_tree, int);
extern void cp_common_init_ts (void);
/* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks
@@ -125,12 +127,16 @@ extern void cp_common_init_ts (void);
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
#undef LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE
#define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE cp_reconstruct_complex_type
+#undef LANG_HOOKS_GET_DEBUG_TYPE
+#define LANG_HOOKS_GET_DEBUG_TYPE cp_get_debug_type
#undef LANG_HOOKS_TO_TARGET_CHARSET
#define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
#undef LANG_HOOKS_GIMPLIFY_EXPR
#define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
#undef LANG_HOOKS_DECL_DWARF_ATTRIBUTE
#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE cp_decl_dwarf_attribute
+#undef LANG_HOOKS_TYPE_DWARF_ATTRIBUTE
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE cp_type_dwarf_attribute
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
#undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
--- gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C.jj 2016-11-03 13:08:27.018538692 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C 2016-11-03 13:09:52.658464983 +0100
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_use_location" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_reference" { xfail { powerpc-ibm-aix* } } } }
+
+struct S;
+typedef int S::*pdm;
+pdm pmf = 0;
--- gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C.jj 2016-11-03 13:08:27.018538692 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C 2016-11-03 13:09:25.723802676 +0100
@@ -0,0 +1,56 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-g -gno-strict-dwarf -dA" }
+// { dg-final { scan-assembler-times " DW_AT_reference" 5 } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 5 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_subroutine_type" 6 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 7 } }
+// { dg-final { scan-assembler-times " DW_AT_use_location" 1 } }
+
+struct S
+{
+ void foo1 ();
+ void bar1 () &;
+ void baz1 () &&;
+ void foo2 () const;
+ void bar2 () const &;
+ void baz2 () const &&;
+ void foo3 () const;
+ void bar3 () const &;
+ void baz3 () const &&;
+ int d;
+};
+
+void
+test ()
+{
+ S s;
+ auto o1 = &S::foo1;
+ auto r1 = &S::bar1;
+ auto z1 = &S::baz1;
+ auto o2 = &S::foo2;
+ auto r2 = &S::bar2;
+ auto z2 = &S::baz2;
+ auto o3 = &S::foo3;
+ auto r3 = &S::bar3;
+ auto z3 = &S::baz3;
+ auto d1 = &S::d;
+ void (S::*o4) () const;
+ o4 = &S::foo3;
+ void (S::*r4) () const &;
+ r4 = &S::bar3;
+ void (S::*z4) () const &&;
+ z4 = &S::baz3;
+ (s.*o1) ();
+ (s.*r1) ();
+ (S ().*z1) ();
+ (s.*o2) ();
+ (s.*r2) ();
+ (S ().*z2) ();
+ (s.*o3) ();
+ (s.*r3) ();
+ (S ().*z3) ();
+ (s.*o4) ();
+ (s.*r4) ();
+ (S ().*z4) ();
+ s.*d1 = 2;
+}
--- gcc/testsuite/g++.dg/debug/dwarf2/ref-4.C.jj 2016-11-03 13:08:55.808177742 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/ref-4.C 2016-11-03 13:11:47.928019792 +0100
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-g -gno-strict-dwarf -dA" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_typedef" 2 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 2 } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_subroutine_type" 1 } }
+
+struct A { void foo (); int a; };
+typedef void (A::*PMF) ();
+typedef int A::*PMI;
+PMF pmf;
+PMI pmi;
--- gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C.jj 2016-11-03 13:08:27.018538692 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C 2016-11-03 13:09:33.829701048 +0100
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_reference" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_use_location" { xfail { powerpc-ibm-aix* } } } }
+/* It is not clear what if anything we should output for
+ DW_AT_use_location in a pointer to member function, so we don't
+ output it for now. */
+
+struct S {
+ void mf(void) &;
+};
+
+void S::mf() & {}
+
+typedef void (S::*pmft)(void) &;
+pmft pmf = &S::mf;
--- gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C.jj 2016-11-03 13:08:27.019538680 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C 2016-11-03 13:09:38.982636443 +0100
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_use_location" { xfail { powerpc-ibm-aix* } } } }
+/* It is not clear what if anything we should output for
+ DW_AT_use_location in a pointer to member function, so we don't
+ output it for now. */
+
+struct S {
+ void mf(void) &&;
+};
+
+void S::mf() && {}
+
+typedef void (S::*pmft)(void) &&;
+pmft pmf = &S::mf;
Jakub
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those
2016-11-02 16:33 ` Jakub Jelinek
2016-11-02 17:19 ` Jason Merrill
@ 2016-11-03 17:31 ` Pierre-Marie de Rodat
1 sibling, 0 replies; 8+ messages in thread
From: Pierre-Marie de Rodat @ 2016-11-03 17:31 UTC (permalink / raw)
To: Jakub Jelinek, Jason Merrill
Cc: Alexandre Oliva, Keith Seitz, Jan Kratochvil, gcc-patches List
Hello all,
On 11/02/2016 05:33 PM, Jakub Jelinek wrote:
> On Wed, Nov 02, 2016 at 04:44:05PM +0100, Jakub Jelinek wrote:
>>> You could find an Ada test that uses the code and verify that the
>>> output stays the same?
>>
>> I can try to find the patch that introduced it and if it contained any
>> testcases.
>
> I couldn't find any unfortunately. Pierre, could you please test if the
> following patch doesn't regress anything in the Ada debug info area?
Yes, DWARF output is hard to test⦠or at least I havenât find a way to
do so in TCL/DejaGNU. ;-)
I have my own Python-based testsuite, which I use everytime I submit a
DIE-related patch. As I said on IRC and as richi and I discussed at the
last cauldron, the plan would be to manage to port the testcase to
GCCâs, but schedule-wise Iâm not able to do that these days⦠For the
record I still plan to do it, though! So, just in case someone would
need/want to run this testsuite, here it is in its current state:
<https://github.com/pmderodat/dwarf-ada-testsuite>.
Anyway, that being said: your patch does not introduce regressions in my
testsuite, so itâs fine as far as Iâm concerned. :-) Thank you for asking!
--
Pierre-Marie de Rodat
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those (take 2)
2016-11-03 16:39 ` [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those (take 2) Jakub Jelinek
@ 2016-11-03 19:54 ` Jason Merrill
0 siblings, 0 replies; 8+ messages in thread
From: Jason Merrill @ 2016-11-03 19:54 UTC (permalink / raw)
To: Jakub Jelinek
Cc: Alexandre Oliva, Keith Seitz, Jan Kratochvil,
Pierre-Marie de Rodat, gcc-patches List
On Thu, Nov 3, 2016 at 12:38 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, Nov 02, 2016 at 01:19:09PM -0400, Jason Merrill wrote:
>> On Wed, Nov 2, 2016 at 12:33 PM, Jakub Jelinek <jakub@redhat.com> wrote:
>> > On Wed, Nov 02, 2016 at 04:44:05PM +0100, Jakub Jelinek wrote:
>> >> which means if gen_type_die or gen_type_die_with_usage doesn't
>> >> use the langhook, then we'd emit a completely useless { __pfn; __delta }
>> >> struct into debug info first, and then in modified_type_die used
>> >> the langhook, get OFFSET_TYPE and probably create the
>> >> DW_TAG_ptr_to_member_type. So I think we really need that.
>> >>
>> >> > > 2) it is used for something Ada-ish I really don't know how to test etc.
>> >> > > to be able to find out if it is safe to call it in
>> >> > > gen_type_die_with_usage too
>> >> >
>> >> > You could find an Ada test that uses the code and verify that the
>> >> > output stays the same?
>> >>
>> >> I can try to find the patch that introduced it and if it contained any
>> >> testcases.
>> >
>> > I couldn't find any unfortunately. Pierre, could you please test if the
>> > following patch doesn't regress anything in the Ada debug info area?
>> >
>> > Here is updated patch I'm going to bootstrap/regtest; it generates the
>> > same debuginfo on ref-3.C testcase.
>>
>> Looks good.
>
> Keith's testing revealed a bug in the patch, that we don't emit
> DW_TAG_typedef for PMF typedefs. Fixed by adding && !typedef_variant_p (type)
> check to the cp_get_debug_type hook, so that we emit the proper typedef
> with the right name and only its DECL_ORIGINAL_TYPE is replaced with
> OFFSET_TYPE handling. I believe that was the only issue, so I think it
> should be ok to enable it always, not just for -gdwarf-5.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
I checked in the hunks introducing check_lang_type separately; the rest is OK.
Jason
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2016-11-03 19:54 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-02 14:31 [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those Jakub Jelinek
2016-11-02 15:31 ` Jason Merrill
2016-11-02 15:44 ` Jakub Jelinek
2016-11-02 16:33 ` Jakub Jelinek
2016-11-02 17:19 ` Jason Merrill
2016-11-03 16:39 ` [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those (take 2) Jakub Jelinek
2016-11-03 19:54 ` Jason Merrill
2016-11-03 17:31 ` [PATCH] DW_TAG_ptr_to_member_type for PMF and DW_AT_{,rvalue_}reference for those Pierre-Marie de Rodat
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).