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]

[PATCH] Emit DW_AT_inline for C++17 inline variables (take 2)


On Mon, Oct 31, 2016 at 10:38:40AM -0400, Jason Merrill wrote:
> > The current DWARF 5 wording is:
> > "If the variable entry represents the defining declaration for a C++ static data
> > member of a structure, class or union, the entry has a DW_AT_specification
> > attribute, whose value is a reference to the debugging information entry
> > representing the declaration of this data member. The referenced entry has
> > the tag DW_TAG_member and will be a child of some class, structure or
> > union type entry." on page 98 in DWARF5_Public_Review.pdf.
> 
> Yes, this changed in DWARF 3; DWARF 2 didn't specify the tag.  I think
> this was a mistake.
> 
> > Incidentally, I've filed today a DWARF issue that Appendix A doesn't list
> > for DW_TAG_member lots of attributes that are allowed for DW_TAG_variable
> > and are useful for static data members.
> 
> Using DW_TAG_variable would address that, too.

After some IRC discussions, following updated patch ensures that even for
inline static data members we emit DW_TAG_member in class with
DW_AT_declaration and DW_TAG_variable outside of the class with
DW_AT_specification pointing to the DW_TAG_member DIE.  DW_AT_location and
DW_AT_linkage_name appear on the DW_TAG_variable DIE,
DW_AT_const_value/DW_AT_const_expr/DW_AT_inline etc. on DW_TAG_member
(except for DW_AT_inline like for non-inline static data members).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-11-01  Jakub Jelinek  <jakub@redhat.com>

	* dwarf2out.c (add_name_and_src_coords_attributes): Add NO_LINKAGE_NAME
	argument, don't call add_linkage_name if it is true.
	(gen_variable_die): For C++ inline static data members, consider the
	initial call when old_die is NULL to be declaration and call
	add_name_and_src_coords_attributes in that case with true as
	NO_LINKAGE_NAME.  Add DW_AT_inline attribute if needed.
	(gen_member_die): For C++ inline static data members, emit a
	definition DIE right away in DW_TAG_compile_unit context.
cp/
	* cp-objcp-common.c (cp_decl_dwarf_attribute): Handle DW_AT_inline.
testsuite/
	* g++.dg/debug/dwarf2/inline-var-1.C: New test.

--- gcc/dwarf2out.c.jj	2016-10-31 22:46:16.932801519 +0100
+++ gcc/dwarf2out.c	2016-11-01 11:51:57.839403234 +0100
@@ -3503,7 +3503,7 @@ static void add_prototyped_attribute (dw
 static dw_die_ref add_abstract_origin_attribute (dw_die_ref, tree);
 static void add_pure_or_virtual_attribute (dw_die_ref, tree);
 static void add_src_coords_attributes (dw_die_ref, tree);
-static void add_name_and_src_coords_attributes (dw_die_ref, tree);
+static void add_name_and_src_coords_attributes (dw_die_ref, tree, bool = false);
 static void add_discr_value (dw_die_ref, dw_discr_value *);
 static void add_discr_list (dw_die_ref, dw_discr_list_ref);
 static inline dw_discr_list_ref AT_discr_list (dw_attr_node *);
@@ -19820,7 +19820,8 @@ add_linkage_name (dw_die_ref die, tree d
    given decl, but only if it actually has a name.  */
 
 static void
-add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
+add_name_and_src_coords_attributes (dw_die_ref die, tree decl,
+				    bool no_linkage_name)
 {
   tree decl_name;
 
@@ -19833,7 +19834,8 @@ add_name_and_src_coords_attributes (dw_d
       if (! DECL_ARTIFICIAL (decl))
 	add_src_coords_attributes (die, decl);
 
-      add_linkage_name (die, decl);
+      if (!no_linkage_name)
+	add_linkage_name (die, decl);
     }
 
 #ifdef VMS_DEBUGGING_INFO
@@ -22215,6 +22217,22 @@ gen_variable_die (tree decl, tree origin
   bool declaration = (DECL_EXTERNAL (decl_or_origin)
 		      || class_or_namespace_scope_p (context_die));
   bool specialization_p = false;
+  bool no_linkage_name = false;
+
+  /* While C++ inline static data members have definitions inside of the
+     class, force the first DIE to be a declaration, then let gen_member_die
+     reparent it to the class context and call gen_variable_die again
+     to create the outside of the class DIE for the definition.  */
+  if (!declaration
+      && old_die == NULL
+      && decl
+      && DECL_CONTEXT (decl)
+      && TYPE_P (DECL_CONTEXT (decl))
+      && lang_hooks.decls.decl_dwarf_attribute (decl, DW_AT_inline) != -1)
+    {
+      declaration = true;
+      no_linkage_name = true;
+    }
 
   ultimate_origin = decl_ultimate_origin (decl_or_origin);
   if (decl || ultimate_origin)
@@ -22402,7 +22420,7 @@ gen_variable_die (tree decl, tree origin
 	}
     }
   else
-    add_name_and_src_coords_attributes (var_die, decl);
+    add_name_and_src_coords_attributes (var_die, decl, no_linkage_name);
 
   if ((origin == NULL && !specialization_p)
       || (origin != NULL
@@ -22465,6 +22483,17 @@ gen_variable_die (tree decl, tree origin
       && (origin_die == NULL || get_AT (origin_die, DW_AT_const_expr) == NULL)
       && !specialization_p)
     add_AT_flag (var_die, DW_AT_const_expr, 1);
+
+  if (!dwarf_strict)
+    {
+      int inl = lang_hooks.decls.decl_dwarf_attribute (decl_or_origin,
+						       DW_AT_inline);
+      if (inl != -1
+	  && !get_AT (var_die, DW_AT_inline)
+	  && (origin_die == NULL || get_AT (origin_die, DW_AT_inline) == NULL)
+	  && !specialization_p)
+	add_AT_unsigned (var_die, DW_AT_inline, inl);
+    }
 }
 
 /* Generate a DIE to represent a named constant.  */
@@ -23622,6 +23651,19 @@ gen_member_die (tree type, dw_die_ref co
 	  vlr_ctx.variant_part_offset = NULL_TREE;
 	  gen_decl_die (member, NULL, &vlr_ctx, context_die);
 	}
+
+      /* For C++ inline static data members emit immediately a DW_TAG_variable
+	 DIE that will refer to that DW_TAG_member through
+	 DW_AT_specification.  */
+      if (TREE_STATIC (member)
+	  && (lang_hooks.decls.decl_dwarf_attribute (member, DW_AT_inline)
+	      != -1))
+	{
+	  int old_extern = DECL_EXTERNAL (member);
+	  DECL_EXTERNAL (member) = 0;
+	  gen_decl_die (member, NULL, NULL, comp_unit_die ());
+	  DECL_EXTERNAL (member) = old_extern;
+	}
     }
 
   /* We do not keep type methods in type variants.  */
--- gcc/cp/cp-objcp-common.c.jj	2016-10-31 13:28:11.080382933 +0100
+++ gcc/cp/cp-objcp-common.c	2016-11-01 10:25:14.123707815 +0100
@@ -199,6 +199,16 @@ cp_decl_dwarf_attribute (const_tree decl
 	return 1;
       break;
 
+    case DW_AT_inline:
+      if (VAR_P (decl) && DECL_INLINE_VAR_P (decl))
+	{
+	  if (DECL_VAR_DECLARED_INLINE_P (decl))
+	    return DW_INL_declared_inlined;
+	  else
+	    return DW_INL_inlined;
+	}
+      break;
+
     default:
       break;
     }
--- gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C.jj	2016-11-01 10:25:14.123707815 +0100
+++ gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C	2016-11-01 11:57:30.044232487 +0100
@@ -0,0 +1,27 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++1z -g -dA -gno-strict-dwarf" }
+// { dg-require-weak "" }
+// { dg-final { scan-assembler-times "0x3\[^\n\r]* DW_AT_inline" 6 } }
+// { dg-final { scan-assembler-times "0x1\[^\n\r]* DW_AT_inline" 2 } }
+// { dg-final { scan-assembler-times " DW_AT_declaration" 6 } }
+// { dg-final { scan-assembler-times " DW_AT_specification" 6 } }
+// { dg-final { scan-assembler-times " DW_AT_\[^\n\r]*linkage_name" 7 } }
+
+inline int a;
+struct S
+{
+  static inline double b = 4.0;
+  static constexpr int c = 2;
+  static constexpr inline char d = 3;
+} s;
+template <int N>
+inline int e = N;
+int &f = e<2>;
+template <int N>
+struct T
+{
+  static inline double g = 4.0;
+  static constexpr int h = 2;
+  static inline constexpr char i = 3;
+};
+T<5> t;


	Jakub


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