[v2] debug: Improve debug info of c++14 deduced return type [PR94459]

Message ID 20200404075405.GM2212@tucnak
State New
Headers show
Series
  • [v2] debug: Improve debug info of c++14 deduced return type [PR94459]
Related show

Commit Message

Xionghu Luo via Gcc-patches April 4, 2020, 7:54 a.m.
On Sat, Apr 04, 2020 at 12:08:38AM -0400, Jason Merrill wrote:
> http://eel.is/c++draft/dcl.spec.auto#3 says it has to appear as a

> decl-specifier.

> 

> http://eel.is/c++draft/temp.deduct.type#8 lists the forms where a template

> argument can be deduced.

> 

> Looks like you are missing arrays, pointers to members, and function return

> types.


I have added that to dwarf2out.c but have a hard time figuring out how to
write the array case (added just the pointer, pointer-to-member (both data
and function) and pointer to function cases to the testcase so far).
Tried
  auto (&m22 ())[2] { return w; }
but that is rejected with:
pr94459.C:40:10: error: ‘m22’ declared as array of ‘auto’
   40 |   auto (&m22 ())[2] { return w; }
      |          ^~~

2020-04-04  Hannes Domani  <ssbssa@yahoo.de>
	    Jakub Jelinek  <jakub@redhat.com>

	PR debug/94459
	* dwarf2out.c (gen_subprogram_die): Look through references, pointers,
	arrays, pointer-to-members, function types and qualifiers when
	checking if in-class DIE had an 'auto' or 'decltype(auto)' return type
	to emit type again on definition.

	* g++.dg/debug/pr94459.C: New test.


	Jakub

Comments

Xionghu Luo via Gcc-patches April 4, 2020, 3:58 p.m. | #1
On 4/4/20 3:54 AM, Jakub Jelinek wrote:
> On Sat, Apr 04, 2020 at 12:08:38AM -0400, Jason Merrill wrote:

>> http://eel.is/c++draft/dcl.spec.auto#3 says it has to appear as a

>> decl-specifier.

>>

>> http://eel.is/c++draft/temp.deduct.type#8 lists the forms where a template

>> argument can be deduced.

>>

>> Looks like you are missing arrays, pointers to members, and function return

>> types.

> 

> I have added that to dwarf2out.c but have a hard time figuring out how to

> write the array case (added just the pointer, pointer-to-member (both data

> and function) and pointer to function cases to the testcase so far).

> Tried

>    auto (&m22 ())[2] { return w; }

> but that is rejected with:

> pr94459.C:40:10: error: ‘m22’ declared as array of ‘auto’

>     40 |   auto (&m22 ())[2] { return w; }

>        |          ^~~


Hmm, that is in fact prohibited by http://eel.is/c++draft/dcl.array#4

"U is called the array element type; this type shall not be a 
placeholder type...."

That restriction seems misplaced, but clearly interferes with testing 
that pattern.  Let's keep the handling in dwarf2out, though.  The patch 
is OK as is.

> 2020-04-04  Hannes Domani  <ssbssa@yahoo.de>

> 	    Jakub Jelinek  <jakub@redhat.com>

> 

> 	PR debug/94459

> 	* dwarf2out.c (gen_subprogram_die): Look through references, pointers,

> 	arrays, pointer-to-members, function types and qualifiers when

> 	checking if in-class DIE had an 'auto' or 'decltype(auto)' return type

> 	to emit type again on definition.

> 

> 	* g++.dg/debug/pr94459.C: New test.

> 

> --- gcc/dwarf2out.c.jj	2020-04-04 00:35:03.450199722 +0200

> +++ gcc/dwarf2out.c	2020-04-04 09:45:27.821396824 +0200

> @@ -22905,11 +22905,22 @@ gen_subprogram_die (tree decl, dw_die_re

>   		  != (unsigned) s.column))

>   	    add_AT_unsigned (subr_die, DW_AT_decl_column, s.column);

>   

> -	  /* If the prototype had an 'auto' or 'decltype(auto)' return type,

> -	     emit the real type on the definition die.  */

> +	  /* If the prototype had an 'auto' or 'decltype(auto)' in

> +	     the return type, emit the real type on the definition die.  */

>   	  if (is_cxx () && debug_info_level > DINFO_LEVEL_TERSE)

>   	    {

>   	      dw_die_ref die = get_AT_ref (old_die, DW_AT_type);

> +	      while (die

> +		     && (die->die_tag == DW_TAG_reference_type

> +			 || die->die_tag == DW_TAG_rvalue_reference_type

> +			 || die->die_tag == DW_TAG_pointer_type

> +			 || die->die_tag == DW_TAG_const_type

> +			 || die->die_tag == DW_TAG_volatile_type

> +			 || die->die_tag == DW_TAG_restrict_type

> +			 || die->die_tag == DW_TAG_array_type

> +			 || die->die_tag == DW_TAG_ptr_to_member_type

> +			 || die->die_tag == DW_TAG_subroutine_type))

> +		die = get_AT_ref (die, DW_AT_type);

>   	      if (die == auto_die || die == decltype_auto_die)

>   		add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),

>   				    TYPE_UNQUALIFIED, false, context_die);

> --- gcc/testsuite/g++.dg/debug/pr94459.C.jj	2020-04-04 09:24:19.655238506 +0200

> +++ gcc/testsuite/g++.dg/debug/pr94459.C	2020-04-04 09:44:07.572588212 +0200

> @@ -0,0 +1,63 @@

> +// PR debug/94459

> +// { dg-do compile { target c++14 } }

> +// { dg-options "-g -dA" }

> +

> +auto

> +baz ()

> +{

> +  return 0L;

> +}

> +

> +template <typename T>

> +struct S

> +{

> +  T v;

> +  T w[2];

> +  S () : v (0), w { 0, 0 } {}

> +  auto m1 () { return v; }

> +  auto &m2 () { return v; }

> +  auto &&m3 () { return (T&&)v; }

> +  const auto m4 () { return v; }

> +  const auto &m5 () { return v; }

> +  const auto &&m6 () { return (T&&)v; }

> +  volatile auto m7 () { return v; }

> +  volatile auto &m8 () { return v; }

> +  volatile auto &&m9 () { return (T&&)v; }

> +  volatile const auto m10 () { return v; }

> +  volatile const auto &m11 () { return v; }

> +  volatile const auto &&m12 () { return (T&&)v; }

> +  const volatile auto m13 () { return v; }

> +  const volatile auto &m14 () { return v; }

> +  const volatile auto &&m15 () { return (T&&)v; }

> +#ifndef __STRICT_ANSI__

> +  __restrict const volatile auto &&m16 () { return (T&&)v; }

> +  const __restrict auto &m17 () { return v; }

> +#endif

> +  auto *m18 () { return &v; }

> +  auto (S::* (m19 ())) () { return &S::m1; }

> +  auto (S::* (m20 ())) { return &S::v; }

> +  auto (*m21 ()) () { return baz; }

> +};

> +

> +S<long> s, u, v;

> +

> +long

> +foo ()

> +{

> +  auto x = s.m19 ();

> +  auto y = s.m20 ();

> +  auto z = s.m21 ();

> +  return s.m1 () + s.m2 () + s.m3 () + s.m4 () + s.m5 ()

> +	 + s.m6 () + s.m7 () + s.m8 () + s.m9 () + s.m10 ()

> +	 + s.m11 () + s.m12 () + s.m13 () + s.m14 () + s.m15 ()

> +#ifndef __STRICT_ANSI__

> +	 + u.m16 () + v.m17 ()

> +#endif

> +	 + *s.m18 () + (s.*x) () + s.*y + z ();

> +}

> +

> +int

> +main ()

> +{

> +  return foo ();

> +}

> 

> 	Jakub

>

Patch

--- gcc/dwarf2out.c.jj	2020-04-04 00:35:03.450199722 +0200
+++ gcc/dwarf2out.c	2020-04-04 09:45:27.821396824 +0200
@@ -22905,11 +22905,22 @@  gen_subprogram_die (tree decl, dw_die_re
 		  != (unsigned) s.column))
 	    add_AT_unsigned (subr_die, DW_AT_decl_column, s.column);
 
-	  /* If the prototype had an 'auto' or 'decltype(auto)' return type,
-	     emit the real type on the definition die.  */
+	  /* If the prototype had an 'auto' or 'decltype(auto)' in
+	     the return type, emit the real type on the definition die.  */
 	  if (is_cxx () && debug_info_level > DINFO_LEVEL_TERSE)
 	    {
 	      dw_die_ref die = get_AT_ref (old_die, DW_AT_type);
+	      while (die
+		     && (die->die_tag == DW_TAG_reference_type
+			 || die->die_tag == DW_TAG_rvalue_reference_type
+			 || die->die_tag == DW_TAG_pointer_type
+			 || die->die_tag == DW_TAG_const_type
+			 || die->die_tag == DW_TAG_volatile_type
+			 || die->die_tag == DW_TAG_restrict_type
+			 || die->die_tag == DW_TAG_array_type
+			 || die->die_tag == DW_TAG_ptr_to_member_type
+			 || die->die_tag == DW_TAG_subroutine_type))
+		die = get_AT_ref (die, DW_AT_type);
 	      if (die == auto_die || die == decltype_auto_die)
 		add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),
 				    TYPE_UNQUALIFIED, false, context_die);
--- gcc/testsuite/g++.dg/debug/pr94459.C.jj	2020-04-04 09:24:19.655238506 +0200
+++ gcc/testsuite/g++.dg/debug/pr94459.C	2020-04-04 09:44:07.572588212 +0200
@@ -0,0 +1,63 @@ 
+// PR debug/94459
+// { dg-do compile { target c++14 } }
+// { dg-options "-g -dA" }
+
+auto
+baz ()
+{
+  return 0L;
+}
+
+template <typename T>
+struct S
+{
+  T v;
+  T w[2];
+  S () : v (0), w { 0, 0 } {}
+  auto m1 () { return v; }
+  auto &m2 () { return v; }
+  auto &&m3 () { return (T&&)v; }
+  const auto m4 () { return v; }
+  const auto &m5 () { return v; }
+  const auto &&m6 () { return (T&&)v; }
+  volatile auto m7 () { return v; }
+  volatile auto &m8 () { return v; }
+  volatile auto &&m9 () { return (T&&)v; }
+  volatile const auto m10 () { return v; }
+  volatile const auto &m11 () { return v; }
+  volatile const auto &&m12 () { return (T&&)v; }
+  const volatile auto m13 () { return v; }
+  const volatile auto &m14 () { return v; }
+  const volatile auto &&m15 () { return (T&&)v; }
+#ifndef __STRICT_ANSI__
+  __restrict const volatile auto &&m16 () { return (T&&)v; }
+  const __restrict auto &m17 () { return v; }
+#endif
+  auto *m18 () { return &v; }
+  auto (S::* (m19 ())) () { return &S::m1; }
+  auto (S::* (m20 ())) { return &S::v; }
+  auto (*m21 ()) () { return baz; }
+};
+
+S<long> s, u, v;
+
+long
+foo ()
+{
+  auto x = s.m19 ();
+  auto y = s.m20 ();
+  auto z = s.m21 ();
+  return s.m1 () + s.m2 () + s.m3 () + s.m4 () + s.m5 ()
+	 + s.m6 () + s.m7 () + s.m8 () + s.m9 () + s.m10 ()
+	 + s.m11 () + s.m12 () + s.m13 () + s.m14 () + s.m15 ()
+#ifndef __STRICT_ANSI__
+	 + u.m16 () + v.m17 ()
+#endif
+	 + *s.m18 () + (s.*x) () + s.*y + z ();
+}
+
+int
+main ()
+{
+  return foo ();
+}