Patchwork Fix for PR debug/46955

login
register
mail settings
Submitter Dodji Seketeli
Date Dec. 16, 2010, 8:30 a.m.
Message ID <m3r5dii0gw.fsf@redhat.com>
Download mbox | patch
Permalink /patch/75724/
State New
Headers show

Comments

Dodji Seketeli - Dec. 16, 2010, 8:30 a.m.
Hello,

Consider this short example:

  struct S { int f; };
  template<int S::*MP> struct T { };
  T<&S::f> v;

The DW_TAG_template_value_param DIE created for type T<&S::f> lacks the
DW_AT_const_value attribute which value should be the value of the
pointer-to-member constant &S::f.

The problem is tree_add_const_value_attribute doesn't know how to fold
the C++ specific PTRMEM_CST representing &S::f.

This patch ensures that template arguments -- especially
PTRMEM_CST nodes -- that are retrieved with
lang_hooks.get_innermost_generic_args and
lang_hooks.types.get_argument_pack_elems are folded enough for the
DWARF emitter.

Bootstrapped and tested on x86_64-unknown-linux against trunk.
Jason Merrill - Dec. 16, 2010, 7:46 p.m.
On 12/16/2010 03:30 AM, Dodji Seketeli wrote:
> +  for (i = 0; i < vec_len; ++i)
> +    {
> +      TREE_VEC_ELT (folded_elems, i) =
> +	  cplus_expand_constant (TREE_VEC_ELT (elems, i));
> +    }

I'd rather avoid calling cplus_expand_constant on non-expression 
template arguments even though it currently works fine; let's check 
!TYPE_P first.  OK with that change.

Jason
H.J. Lu - Jan. 14, 2011, 4:37 p.m.
On Thu, Dec 16, 2010 at 12:30 AM, Dodji Seketeli <dodji@redhat.com> wrote:
> Hello,
>
> Consider this short example:
>
>  struct S { int f; };
>  template<int S::*MP> struct T { };
>  T<&S::f> v;
>
> The DW_TAG_template_value_param DIE created for type T<&S::f> lacks the
> DW_AT_const_value attribute which value should be the value of the
> pointer-to-member constant &S::f.
>
> The problem is tree_add_const_value_attribute doesn't know how to fold
> the C++ specific PTRMEM_CST representing &S::f.
>
> This patch ensures that template arguments -- especially
> PTRMEM_CST nodes -- that are retrieved with
> lang_hooks.get_innermost_generic_args and
> lang_hooks.types.get_argument_pack_elems are folded enough for the
> DWARF emitter.
>
> Bootstrapped and tested on x86_64-unknown-linux against trunk.
>
> --
>        Dodji
>
> commit 7c4f02c2f2c83a9df8e21de0f6ca0c38242bebc0
> Author: Dodji Seketeli <dodji@redhat.com>
> Date:   Wed Dec 15 13:03:44 2010 +0100
>
>    Fix PR debug/46955
>
>    gcc/cp/
>
>        * cp-lang.c (get_template_innermost_arguments_folded)
>        (get_template_argument_pack_elems_folded)
>        (template_arg_needs_folding, fold_cplus_constants): New static
>        functions.
>        (LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS): Set this hook to
>        get_template_innermost_arguments_folded.
>        (LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS): Set this hook to
>        get_template_argument_pack_elems_folded.
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47291

Patch

diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index ff92666..5e50461 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -38,6 +38,8 @@  static void cp_init_ts (void);
 static const char * cxx_dwarf_name (tree t, int verbosity);
 static enum classify_record cp_classify_record (tree type);
 static tree cp_eh_personality (void);
+static tree get_template_innermost_arguments_folded (const_tree);
+static tree get_template_argument_pack_elems_folded (const_tree);
 
 /* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h;
    consequently, there should be very few hooks below.  */
@@ -56,13 +58,13 @@  static tree cp_eh_personality (void);
 	get_primary_template_innermost_parameters
 #undef LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS
 #define LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS \
-	get_template_innermost_arguments
+	get_template_innermost_arguments_folded
 #undef LANG_HOOKS_FUNCTION_PARAMETER_PACK_P
 #define LANG_HOOKS_FUNCTION_PARAMETER_PACK_P \
 	function_parameter_pack_p
 #undef LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS
 #define LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS \
-	get_template_argument_pack_elems
+	get_template_argument_pack_elems_folded
 #undef LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P
 #define LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P \
 	template_template_parameter_p
@@ -165,5 +167,74 @@  cp_eh_personality (void)
   return cp_eh_personality_decl;
 }
 
+/* This is a subroutine of fold_cplus_constants.  It returns TRUE if T
+   is a C++ specific constant that needs to be folded further before
+   being passed to the debug info emitter.  */
+
+static bool
+template_arg_needs_folding (const_tree t)
+{
+  /* For now only PTRMEM_CST nodes are to be folded further.  */
+  if (TREE_CODE (t) == PTRMEM_CST)
+    return true;
+  return false;
+}
+
+/* Fold the elements of the TREE_VEC C which are C++ specific nodes
+   which would need folding so that they can be processed by the debug
+   info emitter. This is a subroutine of
+   get_template_innermost_arguments_folded and
+   get_template_argument_pack_elems_folded.  */
+
+static tree
+fold_cplus_constants (const_tree c)
+{
+  tree folded_elems, elems = CONST_CAST_TREE (c);
+  int vec_len, i;
+
+  if (elems == NULL_TREE || elems == error_mark_node)
+    return elems;
+
+  vec_len = TREE_VEC_LENGTH (elems);
+
+  /* First check if there is at least one element that needs
+     folding. If there is none, we just return ELEMS. Otherwise create
+     and return a new tree vector that contains the folded versions of
+     ELEMS. This is to avoid allocating memory if we don't need
+     to.  */
+  for (i = 0; i < vec_len; ++i)
+    {
+      if (template_arg_needs_folding (TREE_VEC_ELT (elems, i)))
+	break;
+    }
+  if (i == vec_len)
+    return elems;
+
+  folded_elems = make_tree_vec (vec_len);
+  for (i = 0; i < vec_len; ++i)
+    {
+      TREE_VEC_ELT (folded_elems, i) =
+	cplus_expand_constant (TREE_VEC_ELT (elems, i));
+    }
+  return folded_elems;
+}
+
+/* The C++ implementation of the LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS
+   hook. It returns the innermost template arguments of type T, and
+   makes sure those arguments are folded enough for the debug info
+   emitter.  */
+
+static tree
+get_template_innermost_arguments_folded (const_tree t)
+{
+  return fold_cplus_constants (get_template_innermost_arguments (t));
+}
+
+static tree
+get_template_argument_pack_elems_folded (const_tree t)
+{
+  return fold_cplus_constants (get_template_argument_pack_elems (t));
+}
+
 #include "gt-cp-cp-lang.h"
 #include "gtype-cp.h"
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/template-params-8.C b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-8.C
new file mode 100644
index 0000000..2d4a270
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/template-params-8.C
@@ -0,0 +1,15 @@ 
+// Origin PR debug/46955
+// { dg-options "-g -dA" }
+// { dg-do compile }
+
+struct S { int f; };
+template<int S::*MP> struct T { };
+T<&S::f> v;
+
+// For the type of v, we should have this DWARF generated:
+//	.uleb128 0x6	# (DIE (0x57) DW_TAG_template_value_param)
+//	.ascii "MP\0"	# DW_AT_name
+//	.long	0x61	# DW_AT_type
+//	.byte	0	# DW_AT_const_value
+// So let's look for that.
+// { dg-final { scan-assembler "\[^\n\r\]*DIE \(\[^\n\r\]*\) DW_TAG_template_value_param\[^\n\r\]*\[\n\r\]{1,2}\[^\n\r\]*DW_AT_name\[\n\r\]{1,2}\[^\n\r\]*DW_AT_type\[\n\r\]{1,2}\[^\n\r\]*DW_AT_const_value\[\n\r\]{1,2}" } }