This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PR63240] generate debug info for defaulted member functions
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: gcc-patches List <gcc-patches at gcc dot gnu dot org>, ccoutant at gmail dot com
- Date: Fri, 05 Aug 2016 18:47:25 -0300
- Subject: Re: [PR63240] generate debug info for defaulted member functions
- Authentication-results: sourceware.org; auth=none
- References: <oroa5b27zt.fsf@livre.home> <CADzB+2=tRnr6K0ixzkOEJwb_LT5_32TQMQkvrctvgoVpqTCNLQ@mail.gmail.com>
On Aug 4, 2016, Jason Merrill <jason@redhat.com> wrote:
> On Mon, Aug 1, 2016 at 10:57 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
>> * langhooks.h (struct lang_hooks_for_decls): Add
>> function_decl_defaulted_inclass_p and
>> function_decl_defaulted_outofclass_p.
> Maybe one hook that returns unsigned rather than two bool hooks?
There's a suitable lhd that returns int, so I used that instead. I
noticed we should be using const_tree for these, so I adjusted them and,
while at that, I adjusted _deleted and _explicit too. Finally, having
been informed of the constants for _defaulted and _deleted in DwARF v5
drafts, I've dropped the _GNU attributes for these and started using the
values from the draft, adjusting for them to be emitted even for strict
DWARF v5.
Here's what I'm testing. Ok if it regstraps successfully?
[PR63240] generate debug info for defaulted member functions
From: Alexandre Oliva <aoliva@redhat.com>
This implements <http://dwarfstd.org/ShowIssue.php?issue=141215.3>, a
proposal already accepted for inclusion in DWARF-5, but using
DW_AT_GNU_defaulted instead of DW_AT_defaulted as the attribute name,
because the attribute id for DW_AT_defaulted is not yet publicly
available.
for include/ChangeLog
PR debug/63240
* dwarf2.def (DW_AT_deleted, DW_AT_defaulted): New.
* dwarf2.h (enu dwarf_defaulted_attribute): New.
for gcc/ChangeLog
PR debug/63240
* langhooks-def.h
(LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P): Const_tree-ify.
(LANG_HOOKS_FUNCTION_DECL_DELETED_P): Likewise.
(LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Set default.
(LANG_HOOKS_DECLS): Add it.
* langhooks.h (struct lang_hooks_for_decls): Add
function_decl_defaulted. Const_tree-ify
function_decl_explicit_p and function_decl_deleted_p.
* dwarf2out.c (gen_subprogram_die): Add DW_AT_defaulted
attribute. Add DW_AT_deleted instead of DW_AT_GNU_deleted,
also at strict DWARF v5.
for gcc/cp/ChangeLog
PR debug/63240
* cp-objcp-common.c (cp_function_decl_defaulted): New.
(cp_function_decl_explicit_p): Const_tree-ify.
(cp_function_decl_deleted_p): Likewise.
* cp-objcp-common.h (cp_function_decl_defaulted): Declare.
(cp_function_decl_explicit_p): Const_tree-ify.
(cp_function_decl_deleted_p): Likewise.
(LANG_HOOKS_FUNCTION_DECL_DEFAULTED): Redefine.
for gcc/testsuite/ChangeLog
PR debug/63240
* g++.dg/debug/dwarf2/defaulted-member-function-1.C: New.
* g++.dg/debug/dwarf2/defaulted-member-function-2.C: New.
* g++.dg/debug/dwarf2/defaulted-member-function-3.C: New.
* g++.dg/debug/dwarf2/deleted-member-function.C: Expect
DW_AT_deleted.
---
gcc/cp/cp-objcp-common.c | 25 +++++++++-
gcc/cp/cp-objcp-common.h | 7 ++-
gcc/dwarf2out.c | 49 +++++++++++++++++++-
gcc/langhooks-def.h | 6 ++
gcc/langhooks.h | 9 +++-
.../debug/dwarf2/defaulted-member-function-1.C | 14 ++++++
.../debug/dwarf2/defaulted-member-function-2.C | 16 +++++++
.../debug/dwarf2/defaulted-member-function-3.C | 13 +++++
.../g++.dg/debug/dwarf2/deleted-member-function.C | 2 -
include/dwarf2.def | 2 +
include/dwarf2.h | 8 +++
11 files changed, 139 insertions(+), 12 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-1.C
create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-2.C
create mode 100644 gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-3.C
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index f7ddb00..9cb9dd7 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -133,7 +133,7 @@ cxx_types_compatible_p (tree x, tree y)
/* Return true if DECL is explicit member function. */
bool
-cp_function_decl_explicit_p (tree decl)
+cp_function_decl_explicit_p (const_tree decl)
{
return (decl
&& DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
@@ -143,13 +143,34 @@ cp_function_decl_explicit_p (tree decl)
/* Return true if DECL is deleted special member function. */
bool
-cp_function_decl_deleted_p (tree decl)
+cp_function_decl_deleted_p (const_tree decl)
{
return (decl
&& DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
&& DECL_DELETED_FN (decl));
}
+/* Returns 0 if DECL is NOT a C++11 defaulted special member function,
+ 1 if it is explicitly defaulted within the class body, or 2 if it
+ is explicitly defaulted outside the class body. */
+
+int
+cp_function_decl_defaulted (const_tree decl)
+{
+ if (decl
+ && DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
+ && DECL_DEFAULTED_FN (decl))
+ {
+ if (DECL_DEFAULTED_IN_CLASS_P (decl))
+ return 1;
+
+ if (DECL_DEFAULTED_OUTSIDE_CLASS_P (decl))
+ return 2;
+ }
+
+ return 0;
+}
+
/* Stubs to keep c-opts.c happy. */
void
push_file_scope (void)
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 1bb19ee..3ad3eb6 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -26,8 +26,9 @@ along with GCC; see the file COPYING3. If not see
extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
tree, bool);
-extern bool cp_function_decl_explicit_p (tree decl);
-extern bool cp_function_decl_deleted_p (tree decl);
+extern bool cp_function_decl_explicit_p (const_tree decl);
+extern bool cp_function_decl_deleted_p (const_tree decl);
+extern int cp_function_decl_defaulted (const_tree decl);
extern void cp_common_init_ts (void);
/* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks
@@ -134,6 +135,8 @@ extern void cp_common_init_ts (void);
#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P cp_function_decl_explicit_p
#undef LANG_HOOKS_FUNCTION_DECL_DELETED_P
#define LANG_HOOKS_FUNCTION_DECL_DELETED_P cp_function_decl_deleted_p
+#undef LANG_HOOKS_FUNCTION_DECL_DEFAULTED
+#define LANG_HOOKS_FUNCTION_DECL_DEFAULTED cp_function_decl_defaulted
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
#undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 8d6eeed..1b2e48f 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -20399,6 +20399,24 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),
TYPE_UNQUALIFIED, false, context_die);
}
+
+ /* When we process the method declaration, we haven't seen
+ the out-of-class defaulted definition yet, so we have to
+ recheck now. */
+ int defaulted = lang_hooks.decls.function_decl_defaulted (decl);
+ if (defaulted && (dwarf_version >= 5 || ! dwarf_strict)
+ && !get_AT (subr_die, DW_AT_defaulted))
+ switch (defaulted)
+ {
+ case 2:
+ add_AT_unsigned (subr_die, DW_AT_defaulted,
+ DW_DEFAULTED_out_of_class);
+ break;
+
+ case 1: /* This must have been handled before. */
+ default:
+ gcc_unreachable ();
+ }
}
}
/* Create a fresh DIE for anything else. */
@@ -20446,10 +20464,35 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
add_AT_flag (subr_die, DW_AT_explicit, 1);
/* If this is a C++11 deleted special function member then generate
- a DW_AT_GNU_deleted attribute. */
+ a DW_AT_deleted attribute. */
if (lang_hooks.decls.function_decl_deleted_p (decl)
- && (! dwarf_strict))
- add_AT_flag (subr_die, DW_AT_GNU_deleted, 1);
+ && (dwarf_version >= 5 || ! dwarf_strict))
+ add_AT_flag (subr_die, DW_AT_deleted, 1);
+
+ /* If this is a C++11 defaulted special function member then
+ generate a DW_AT_GNU_defaulted attribute. */
+ int defaulted = lang_hooks.decls.function_decl_defaulted (decl);
+ if (defaulted && (dwarf_version >= 5 || ! dwarf_strict))
+ switch (defaulted)
+ {
+ case 1:
+ add_AT_unsigned (subr_die, DW_AT_defaulted,
+ DW_DEFAULTED_in_class);
+ break;
+
+ /* It is likely that this will never hit, since we
+ don't have the out-of-class definition yet when we
+ process the class definition and the method
+ declaration. We recheck elsewhere, but leave it
+ here just in case. */
+ case 2:
+ add_AT_unsigned (subr_die, DW_AT_defaulted,
+ DW_DEFAULTED_out_of_class);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
}
}
/* Tag abstract instances with DW_AT_inline. */
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index 034b3b7..5a66841 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -208,8 +208,9 @@ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_GLOBAL_BINDINGS_P global_bindings_p
#define LANG_HOOKS_PUSHDECL pushdecl
#define LANG_HOOKS_GETDECLS getdecls
-#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P hook_bool_tree_false
-#define LANG_HOOKS_FUNCTION_DECL_DELETED_P hook_bool_tree_false
+#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P hook_bool_const_tree_false
+#define LANG_HOOKS_FUNCTION_DECL_DELETED_P hook_bool_const_tree_false
+#define LANG_HOOKS_FUNCTION_DECL_DEFAULTED hook_int_const_tree_0
#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl
#define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS NULL
#define LANG_HOOKS_DECL_OK_FOR_SIBCALL lhd_decl_ok_for_sibcall
@@ -232,6 +233,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_GETDECLS, \
LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \
LANG_HOOKS_FUNCTION_DECL_DELETED_P, \
+ LANG_HOOKS_FUNCTION_DECL_DEFAULTED, \
LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \
LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \
LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 0593424..6a4f250 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -181,10 +181,15 @@ struct lang_hooks_for_decls
tree (*getdecls) (void);
/* Returns true if DECL is explicit member function. */
- bool (*function_decl_explicit_p) (tree);
+ bool (*function_decl_explicit_p) (const_tree);
/* Returns true if DECL is C++11 deleted special member function. */
- bool (*function_decl_deleted_p) (tree);
+ bool (*function_decl_deleted_p) (const_tree);
+
+ /* Returns 0 if DECL is NOT a C++11 defaulted special member
+ function, 1 if it is explicitly defaulted within the class body,
+ or 2 if it is explicitly defaulted outside the class body. */
+ int (*function_decl_defaulted) (const_tree);
/* Returns True if the parameter is a generic parameter decl
of a generic type, e.g a template template parameter for the C++ FE. */
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-1.C
new file mode 100644
index 0000000..e798b49
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-1.C
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "0x1\[ \t\]\[^\n\]* DW_AT_defaulted" 1 { xfail { powerpc-ibm-aix* } } } }
+
+struct Foo
+{
+ Foo () = default;
+};
+
+void
+bar ()
+{
+ Foo foo;
+}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-2.C
new file mode 100644
index 0000000..5b56949
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-2.C
@@ -0,0 +1,16 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "0x2\[ \t\]\[^\n\]* DW_AT_defaulted" 1 { xfail { powerpc-ibm-aix* } } } }
+
+struct Foo
+{
+ Foo ();
+};
+
+Foo::Foo () = default;
+
+void
+bar ()
+{
+ Foo foo;
+}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-3.C
new file mode 100644
index 0000000..190fe50
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/defaulted-member-function-3.C
@@ -0,0 +1,13 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-not " DW_AT_defaulted" { xfail { powerpc-ibm-aix* } } } }
+
+struct Foo
+{
+};
+
+void
+bar ()
+{
+ Foo foo;
+}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/deleted-member-function.C b/gcc/testsuite/g++.dg/debug/dwarf2/deleted-member-function.C
index c0c36a9..7f42719 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/deleted-member-function.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/deleted-member-function.C
@@ -1,6 +1,6 @@
// { dg-do compile }
// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
-// { dg-final { scan-assembler-times " DW_AT_GNU_deleted" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_deleted" 2 { xfail { powerpc-ibm-aix* } } } }
struct Foo
{
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 2dfee56..67b2a5b 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -310,6 +310,8 @@ DW_AT (DW_AT_enum_class, 0x6d)
DW_AT (DW_AT_linkage_name, 0x6e)
/* DWARF 5. */
DW_AT (DW_AT_noreturn, 0x87)
+DW_AT (DW_AT_deleted, 0x8a)
+DW_AT (DW_AT_defaulted, 0x8b)
DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start. */
DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end. */
diff --git a/include/dwarf2.h b/include/dwarf2.h
index 1a145aa..d166a96 100644
--- a/include/dwarf2.h
+++ b/include/dwarf2.h
@@ -342,6 +342,14 @@ enum dwarf_macinfo_record_type
DW_MACINFO_vendor_ext = 255
};
+/* DW_TAG_GNU_defaulted/DW_TAG_defaulted attributes. */
+enum dwarf_defaulted_attribute
+ {
+ DW_DEFAULTED_no = 0x00,
+ DW_DEFAULTED_in_class = 0x01,
+ DW_DEFAULTED_out_of_class = 0x02
+ };
+
/* Names and codes for new style macro information. */
enum dwarf_macro_record_type
{
--
Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/ FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer