This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PR63240] generate debug info for defaulted member functions


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]