Bug 79289 - DWARF info for typeof of C function with no args and no prototype is empty pointer
Summary: DWARF info for typeof of C function with no args and no prototype is empty po...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 7.0.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-debug
Depends on:
Blocks:
 
Reported: 2017-01-30 18:06 UTC by Ian Lance Taylor
Modified: 2017-01-30 22:29 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ian Lance Taylor 2017-01-30 18:06:45 UTC
Compile this program with current mainline with -g on GNU/Linux:

static void sub() {}
void f1() { sub(); }
void f2(void) { sub(); }
__typeof__(f1) *v1;
__typeof__(f2) *v2;

Using readelf --debug to examine the debug info I see this for v1:

<1><2d>: Abbrev Number: 2 (DW_TAG_variable)
    <2e>   DW_AT_name        : v1       
    <31>   DW_AT_decl_file   : 1        
    <32>   DW_AT_decl_line   : 4        
    <33>   DW_AT_type        : <0x41>   
    <37>   DW_AT_external    : 1        
    <37>   DW_AT_location    : 9 byte block: 3 8 0 0 0 0 0 0 0  (DW_OP_addr: 8)
 <1><41>: Abbrev Number: 3 (DW_TAG_pointer_type)
    <42>   DW_AT_byte_size   : 8        

Note that the type of v1 is a pointer, but there is no type listed for what it points to.

By comparison, the debug info for v2 is:

 <1><43>: Abbrev Number: 4 (DW_TAG_subroutine_type)
    <44>   DW_AT_prototyped  : 1        
 <1><44>: Abbrev Number: 2 (DW_TAG_variable)
    <45>   DW_AT_name        : v2       
    <48>   DW_AT_decl_file   : 1        
    <49>   DW_AT_decl_line   : 5        
    <4a>   DW_AT_type        : <0x58>   
    <4e>   DW_AT_external    : 1        
    <4e>   DW_AT_location    : 9 byte block: 3 8 0 0 0 0 0 0 0  (DW_OP_addr: 8)
 <1><58>: Abbrev Number: 5 (DW_TAG_pointer_type)
    <59>   DW_AT_byte_size   : 8        
    <5a>   DW_AT_type        : <0x43>   

Here the type of v2 is clearly a pointer to a function, although there is no real information about the function: just that it is prototyped.


By comparison, with GCC 6, I see this for v1:

 <1><29>: Abbrev Number: 2 (DW_TAG_subroutine_type)
    <2a>   DW_AT_sibling     : <0x30>   
 <2><2e>: Abbrev Number: 3 (DW_TAG_unspecified_parameters)
 <2><2f>: Abbrev Number: 0
 <1><30>: Abbrev Number: 4 (DW_TAG_variable)
    <31>   DW_AT_name        : v1       
    <34>   DW_AT_decl_file   : 1        
    <35>   DW_AT_decl_line   : 4        
    <36>   DW_AT_type        : <0x44>   
    <3a>   DW_AT_external    : 1        
    <3a>   DW_AT_location    : 9 byte block: 3 8 0 0 0 0 0 0 0  (DW_OP_addr: 8)
 <1><44>: Abbrev Number: 5 (DW_TAG_pointer_type)
    <45>   DW_AT_byte_size   : 8        
    <46>   DW_AT_type        : <0x29>   

and I see this for v2 (the same as for GCC 7):

 <1><4a>: Abbrev Number: 6 (DW_TAG_subroutine_type)
    <4b>   DW_AT_prototyped  : 1        
 <1><4b>: Abbrev Number: 4 (DW_TAG_variable)
    <4c>   DW_AT_name        : v2       
    <4f>   DW_AT_decl_file   : 1        
    <50>   DW_AT_decl_line   : 5        
    <51>   DW_AT_type        : <0x5f>   
    <55>   DW_AT_external    : 1        
    <55>   DW_AT_location    : 9 byte block: 3 8 0 0 0 0 0 0 0  (DW_OP_addr: 8)
 <1><5f>: Abbrev Number: 5 (DW_TAG_pointer_type)
    <60>   DW_AT_byte_size   : 8        
    <61>   DW_AT_type        : <0x4a>   


I'm not entirely sure what is correct here, but a pointer type that doesn't point to anything must be wrong.  The change from GCC 6 to GCC 7 in the debug info for v1 is a regression.
Comment 1 Ian Lance Taylor 2017-01-30 18:50:37 UTC
I think the bug is a mismatch in how the code determines the base type to use for the DIE in this change:

2016-11-03  Jakub Jelinek  <jakub@redhat.com>
	    Alexandre Oliva  <aoliva@redhat.com>
	    Jason Merrill  <jason@redhat.com>

	PR debug/28767
	PR debug/56974
	* langhooks.h (struct lang_hooks_for_types): Add type_dwarf_attribute
	langhook.
	* langhooks.c (lhd_type_dwarf_attribute): New function.
	* langhooks-def.h (lhd_type_dwarf_attribute): Declare.
	(LANG_HOOKS_TYPE_DWARF_ATTRIBUTE): Define.
	(LANG_HOOKS_FOR_TYPES_INITIALIZER): Add
	LANG_HOOKS_TYPE_DWARF_ATTRIBUTE.
	(check_qualified_type, check_aligned_type): Call it.
	* dwarf2out.c (modified_type_die): Don't use type_main_variant
	for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
	check_base_type and check_lang_type.
	(gen_ptr_to_mbr_type_die): If lookup_type_die is already non-NULL,
	return early.  For pointer-to-data-member add DW_AT_use_location
	attribute.
	(gen_subroutine_type_die): Add DW_AT_{,rvalue_}reference attribute
	if needed.
	(gen_type_die_with_usage): Don't use type_main_variant
	for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
	check_base_type and check_lang_type.  Formatting fixes. Call
	get_debug_type langhook.

The problem is that the DIE is stored with one type variant in gen_type_die_with_usage (the last matching variant), but looked up with a different type variant in modified_type_die (the first matching variant).

This patch seems to fix the problem, but I can't tell whether this is correct or whether the other obvious change is correct.


Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 244166)
+++ gcc/dwarf2out.c	(working copy)
@@ -24395,8 +24395,13 @@ gen_type_die_with_usage (tree type, dw_d
 	 but try to canonicalize.  */
       tree main = TYPE_MAIN_VARIANT (type);
       for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
-	if (check_base_type (t, main) && check_lang_type (t, type))
-	  type = t;
+	{
+	  if (check_base_type (t, main) && check_lang_type (t, type))
+	    {
+	      type = t;
+	      break;
+	    }
+	}
     }
   else if (TREE_CODE (type) != VECTOR_TYPE
 	   && TREE_CODE (type) != ARRAY_TYPE)
Comment 2 Jason Merrill 2017-01-30 20:03:24 UTC
(In reply to Ian Lance Taylor from comment #1)
> This patch seems to fix the problem, but I can't tell whether this is
> correct or whether the other obvious change is correct.

This one looks good.
Comment 3 ian@gcc.gnu.org 2017-01-30 22:26:58 UTC
Author: ian
Date: Mon Jan 30 22:26:26 2017
New Revision: 245039

URL: https://gcc.gnu.org/viewcvs?rev=245039&root=gcc&view=rev
Log:
	PR debug/79289
	* dwarf2out.c (gen_type_die_with_usage): When picking a variant
	for FUNCTION_TYPE/METHOD_TYPE, use the first matching one.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/dwarf2out.c
Comment 4 Ian Lance Taylor 2017-01-30 22:29:06 UTC
Patch committed.