diff mbox

C++ PATCH for c++/53756 (-g and C++1y auto)

Message ID 52E7E353.3020604@redhat.com
State New
Headers show

Commit Message

Jason Merrill Jan. 28, 2014, 5:05 p.m. UTC
My earlier work to support return type deduction omitted support for 
debugging information; this patch fixes that oversight.  It also 
corrects the mangled name of 'operator auto', which should reflect the 
'auto' rather than the deduced return type.

Tested x86_64-pc-linux-gnu, applying to trunk.

Comments

Paolo Carlini Jan. 28, 2014, 6:33 p.m. UTC | #1
On 01/28/2014 06:05 PM, Jason Merrill wrote:
> My earlier work to support return type deduction omitted support for 
> debugging information; this patch fixes that oversight.  It also 
> corrects the mangled name of 'operator auto', which should reflect the 
> 'auto' rather than the deduced return type.
>
> Tested x86_64-pc-linux-gnu, applying to trunk.
Ah! Then I guess that in order to fix c++/58561 only is_base_type needs 
tweaking: shall we change the default to just return 0?

Thanks,
Paolo.
Jason Merrill Jan. 28, 2014, 9:02 p.m. UTC | #2
On 01/28/2014 01:33 PM, Paolo Carlini wrote:
> Ah! Then I guess that in order to fix c++/58561 only is_base_type needs
> tweaking: shall we change the default to just return 0?

Makes sense.

Jason
Andreas Schwab Jan. 29, 2014, 10:37 a.m. UTC | #3
Jason Merrill <jason@redhat.com> writes:

> +// { dg-final { scan-assembler "a1.*(0x\[0-9a-f\]+)\[ \t\]*# DW_AT_type.*\\1. DW_TAG_unspecified_type.*DW_AT_specification\[\n\r\]{1,2}\[^\n\r\]*(0x\[0-9a-f\]+)\[ \t\]*# DW_AT_type.*\\2. DW_TAG_base_type" } }

This regexp is completely broken.

Here's what I get on m68k:

	.uleb128 0x3	| (DIE (0x2b) DW_TAG_subprogram)
			| DW_AT_external
	.ascii "a1\0"	| DW_AT_name
	.byte	0x1	| DW_AT_decl_file (/daten/aranym/gcc/gcc-20140129/gcc/testsuite/g++.dg/debug/dwarf2/auto1.C)
	.byte	0x17	| DW_AT_decl_line
	.long	.LASF2	| DW_AT_linkage_name: "_ZN1A2a1Ev"
	.long	0x44	| DW_AT_type
			| DW_AT_declaration
	.long	0x3d	| DW_AT_object_pointer
	.uleb128 0x4	| (DIE (0x3d) DW_TAG_formal_parameter)
	.long	0x49	| DW_AT_type
			| DW_AT_artificial
	.byte	0	| end of children of DIE 0x2b
	.byte	0	| end of children of DIE 0x21
	.uleb128 0x5	| (DIE (0x44) DW_TAG_unspecified_type)
	.long	.LASF3	| DW_AT_name: "auto"
	.uleb128 0x6	| (DIE (0x49) DW_TAG_pointer_type)
	.byte	0x4	| DW_AT_byte_size
	.long	0x21	| DW_AT_type
	.uleb128 0x7	| (DIE (0x4f) DW_TAG_subprogram)
	.long	0x2b	| DW_AT_specification
	.long	0x77	| DW_AT_type
	.long	.LFB0	| DW_AT_low_pc
	.long	.LFE0-.LFB0	| DW_AT_high_pc
	.uleb128 0x1	| DW_AT_frame_base
	.byte	0x9c	| DW_OP_call_frame_cfa
	.long	0x6a	| DW_AT_object_pointer
			| DW_AT_GNU_all_call_sites
	.long	0x77	| DW_AT_sibling
	.uleb128 0x8	| (DIE (0x6a) DW_TAG_formal_parameter)
	.long	.LASF4	| DW_AT_name: "this"
	.long	0x7e	| DW_AT_type
			| DW_AT_artificial
	.uleb128 0x2	| DW_AT_location
	.byte	0x91	| DW_OP_fbreg
	.sleb128 0
	.byte	0	| end of children of DIE 0x4f
	.uleb128 0x9	| (DIE (0x77) DW_TAG_base_type)
	.byte	0x4	| DW_AT_byte_size
	.byte	0x5	| DW_AT_encoding
	.ascii "int\0"	| DW_AT_name

And this is what I get on ia64:

	.uleb128 0x3	// (DIE (0x2f) DW_TAG_subprogram)
			// DW_AT_external
	.ascii "a1\0"	// DW_AT_name
	data1	0x1	// DW_AT_decl_file (/usr/local/gcc/gcc-20140129/gcc/testsuite/g++.dg/debug/dwarf2/auto1.C)
	data1	0x17	// DW_AT_decl_line
	data4.ua	@secrel(.LASF2)	// DW_AT_linkage_name: "_ZN1A2a1Ev"
	data4.ua	0x48	// DW_AT_type
			// DW_AT_declaration
	data4.ua	0x41	// DW_AT_object_pointer
	.uleb128 0x4	// (DIE (0x41) DW_TAG_formal_parameter)
	data4.ua	0x4d	// DW_AT_type
			// DW_AT_artificial
	data1	0	// end of children of DIE 0x2f
	data1	0	// end of children of DIE 0x25
	.uleb128 0x5	// (DIE (0x48) DW_TAG_unspecified_type)
	data4.ua	@secrel(.LASF3)	// DW_AT_name: "auto"
	.uleb128 0x6	// (DIE (0x4d) DW_TAG_pointer_type)
	data1	0x8	// DW_AT_byte_size
	data4.ua	0x25	// DW_AT_type
	.uleb128 0x7	// (DIE (0x53) DW_TAG_subprogram)
	data4.ua	0x2f	// DW_AT_specification
	data4.ua	0x85	// DW_AT_type
	data8.ua	.LFB0	// DW_AT_low_pc
	data8.ua	.LFE0-.LFB0	// DW_AT_high_pc
	data4.ua	@secrel(.LLST0)	// DW_AT_frame_base
	data4.ua	0x78	// DW_AT_object_pointer
			// DW_AT_GNU_all_call_sites
	data4.ua	0x85	// DW_AT_sibling
	.uleb128 0x8	// (DIE (0x78) DW_TAG_formal_parameter)
	data4.ua	@secrel(.LASF4)	// DW_AT_name: "this"
	data4.ua	0x8c	// DW_AT_type
			// DW_AT_artificial
	.uleb128 0x2	// DW_AT_location
	data1	0x91	// DW_OP_fbreg
	.sleb128 0
	data1	0	// end of children of DIE 0x53
	.uleb128 0x9	// (DIE (0x85) DW_TAG_base_type)
	data1	0x4	// DW_AT_byte_size
	data1	0x5	// DW_AT_encoding
	.ascii "int\0"	// DW_AT_name

Andreas.
Jason Merrill Jan. 29, 2014, 5:01 p.m. UTC | #4
On 01/29/2014 05:37 AM, Andreas Schwab wrote:
> Jason Merrill <jason@redhat.com> writes:
>
>> +// { dg-final { scan-assembler "a1.*(0x\[0-9a-f\]+)\[ \t\]*# DW_AT_type.*\\1. DW_TAG_unspecified_type.*DW_AT_specification\[\n\r\]{1,2}\[^\n\r\]*(0x\[0-9a-f\]+)\[ \t\]*# DW_AT_type.*\\2. DW_TAG_base_type" } }
>
> This regexp is completely broken.

I'll fix it shortly.

Jason
diff mbox

Patch

commit 2b1d597e10480dfc2aefe251990cacc2af11d7cc
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Nov 6 12:02:55 2013 -0500

    	PR c++/53756
    gcc/
    	* dwarf2out.c (auto_die): New static.
    	(gen_type_die_with_usage): Handle C++1y 'auto'.
    	(gen_subprogram_die): If in-class DIE had 'auto', emit type again
    	on definition.
    gcc/cp/
    	* mangle.c (write_unqualified_name): Handle operator auto.

diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index be3c698..add73cf 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1231,6 +1231,9 @@  write_unqualified_name (const tree decl)
 	      fn_type = get_mostly_instantiated_function_type (decl);
 	      type = TREE_TYPE (fn_type);
 	    }
+	  else if (FNDECL_USED_AUTO (decl))
+	    type = (DECL_STRUCT_FUNCTION (decl)->language
+		    ->x_auto_return_pattern);
 	  else
 	    type = DECL_CONV_FN_TYPE (decl);
 	  write_conversion_operator_name (type);
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 22282d8..f6efd1f 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -247,6 +247,9 @@  static GTY(()) bool cold_text_section_used = false;
 /* The default cold text section.  */
 static GTY(()) section *cold_text_section;
 
+/* The DIE for C++1y 'auto' in a function return type.  */
+static GTY(()) dw_die_ref auto_die;
+
 /* Forward declarations for functions defined in this file.  */
 
 static char *stripattributes (const char *);
@@ -17999,6 +18002,13 @@  gen_subprogram_die (tree decl, dw_die_ref context_die)
 	    add_AT_file (subr_die, DW_AT_decl_file, file_index);
 	  if (get_AT_unsigned (old_die, DW_AT_decl_line) != (unsigned) s.line)
 	    add_AT_unsigned (subr_die, DW_AT_decl_line, s.line);
+
+	  /* If the prototype had an 'auto' return type, emit the real
+	     type on the definition die.  */
+	  if (is_cxx() && debug_info_level > DINFO_LEVEL_TERSE
+	      && get_AT_ref (old_die, DW_AT_type) == auto_die)
+	    add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),
+				0, 0, context_die);
 	}
     }
   else
@@ -19820,6 +19830,25 @@  gen_type_die_with_usage (tree type, dw_die_ref context_die,
       break;
 
     default:
+      // A C++ function with deduced return type can have
+      // a TEMPLATE_TYPE_PARM named 'auto' in its type.
+      if (is_cxx ())
+	{
+	  tree name = TYPE_NAME (type);
+	  if (TREE_CODE (name) == TYPE_DECL)
+	    name = DECL_NAME (name);
+	  if (name == get_identifier ("auto"))
+	    {
+	      if (!auto_die)
+		{
+		  auto_die = new_die (DW_TAG_unspecified_type,
+				      comp_unit_die (), NULL_TREE);
+		  add_name_attribute (auto_die, "auto");
+		}
+	      equate_type_number_to_die (type, auto_die);
+	      break;
+	    }
+	}
       gcc_unreachable ();
     }
 
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C
index e4e58e8..ab4a1bb 100644
--- a/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn12.C
@@ -1,5 +1,5 @@ 
 // { dg-options -std=c++1y }
-// { dg-final { scan-assembler "_ZN1AIiEcviEv" } }
+// { dg-final { scan-assembler "_ZN1AIiEcvDaEv" } }
 
 template <class T>
 struct A {
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn22.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn22.C
new file mode 100644
index 0000000..f05cbb9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn22.C
@@ -0,0 +1,9 @@ 
+// { dg-options "-std=c++1y" }
+
+struct A
+{
+  operator auto();
+};
+
+// { dg-final { scan-assembler "_ZN1AcvDaEv" } }
+A::operator auto() { return 42; }
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/auto1.C b/gcc/testsuite/g++.dg/debug/dwarf2/auto1.C
new file mode 100644
index 0000000..188ca11
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/auto1.C
@@ -0,0 +1,30 @@ 
+// PR c++/53756
+// { dg-options "-std=c++1y -g -dA -fno-debug-types-section" }
+// We're looking for something like
+
+// .uleb128 0x3    # (DIE (0x33) DW_TAG_subprogram)
+// .ascii "a1\0"   # DW_AT_name
+// .long   0x4c    # DW_AT_type
+//...
+// .uleb128 0x5    # (DIE (0x4c) DW_TAG_unspecified_type)
+// .long   .LASF6  # DW_AT_name: "auto"
+//...
+// .uleb128 0x7    # (DIE (0x57) DW_TAG_subprogram)
+// .long   0x33    # DW_AT_specification
+// .long   0x87    # DW_AT_type
+//...
+// .uleb128 0x9    # (DIE (0x87) DW_TAG_base_type)
+// .ascii "int\0"  # DW_AT_name
+
+// { dg-final { scan-assembler "a1.*(0x\[0-9a-f\]+)\[ \t\]*# DW_AT_type.*\\1. DW_TAG_unspecified_type.*DW_AT_specification\[\n\r\]{1,2}\[^\n\r\]*(0x\[0-9a-f\]+)\[ \t\]*# DW_AT_type.*\\2. DW_TAG_base_type" } }
+
+struct A
+{
+  auto a1 () { return 42; }
+};
+
+int main()
+{
+  A a;
+  a.a1();
+}