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]

Re: [PATCH] Emit DWARF5 DW_AT_reference and DW_AT_rvalue_reference


On Mon, Oct 31, 2016 at 09:56:28AM -0400, Jason Merrill wrote:
> >Or by changing get_qualified_die (in particular check_base_type) to use a
> >langhook, we could at least for DW_AT_{reference,rvalue_reference} just use
> >equate_type_number_to_die/lookup_type_die reliably (DW_AT_endianity issue
> >remains).
> 
> Yeah, I think that adding a langhook is the right way to go.  The generic
> code clobbering C++ qualifiers is a frequent headache.

I've tried to implement that, but am getting some TYPE_CANONICAL differences
because of that, and am really lost what the problem is and how to fix it.
Furthermore, I bet the exception specification also should be considered in
that langhook.

The testcase I've been trying is:

struct S
{
  void foo1 ();
  void bar1 () &;
  void baz1 () &&;
  void foo2 () const;
  void bar2 () const &;
  void baz2 () const &&;
  void foo3 () const;
  void bar3 () const &;
  void baz3 () const &&;
};

void
test ()
{
  S s;
  auto o1 = &S::foo1;
  auto r1 = &S::bar1;
  auto z1 = &S::baz1;
  auto o2 = &S::foo2;
  auto r2 = &S::bar2;
  auto z2 = &S::baz2;
  auto o3 = &S::foo3;
  auto r3 = &S::bar3;
  auto z3 = &S::baz3;
  void (S::*o4) () const;
  o4 = &S::foo3;
  void (S::*r4) () const &;
  r4 = &S::bar3;
  void (S::*z4) () const &&;
  z4 = &S::baz3;
  (s.*o1) ();
  (s.*r1) ();
  (S ().*z1) ();
  (s.*o2) ();
  (s.*r2) ();
  (S ().*z2) ();
  (s.*o3) ();
  (s.*r3) ();
  (S ().*z3) ();
  (s.*o4) ();
  (s.*r4) ();
  (S ().*z4) ();
}

--- gcc/hooks.h.jj	2016-10-31 13:28:06.000000000 +0100
+++ gcc/hooks.h	2016-11-01 12:55:33.662494341 +0100
@@ -59,6 +59,7 @@ extern bool hook_bool_rtx_mode_int_int_i
 							int, int, int *, bool);
 extern bool hook_bool_tree_tree_false (tree, tree);
 extern bool hook_bool_tree_tree_true (tree, tree);
+extern bool hook_bool_const_tree_const_tree_true (const_tree, const_tree);
 extern bool hook_bool_tree_bool_false (tree, bool);
 extern bool hook_bool_wint_wint_uint_bool_true (const widest_int &,
 						const widest_int &,
--- gcc/cp/cp-objcp-common.h.jj	2016-10-31 13:28:11.000000000 +0100
+++ gcc/cp/cp-objcp-common.h	2016-11-01 12:56:44.446605921 +0100
@@ -27,6 +27,8 @@ extern tree objcp_tsubst_copy_and_build
 					 tree, bool);
 
 extern int cp_decl_dwarf_attribute (const_tree, int);
+extern int cp_type_dwarf_attribute (const_tree, int);
+extern bool cp_check_base_type (const_tree, const_tree);
 extern void cp_common_init_ts (void);
 
 /* Lang hooks that are shared between C++ and ObjC++ are defined here.  Hooks
@@ -131,6 +133,10 @@ extern void cp_common_init_ts (void);
 #define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
 #undef LANG_HOOKS_DECL_DWARF_ATTRIBUTE
 #define LANG_HOOKS_DECL_DWARF_ATTRIBUTE cp_decl_dwarf_attribute
+#undef LANG_HOOKS_TYPE_DWARF_ATTRIBUTE
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE cp_type_dwarf_attribute
+#undef LANG_HOOKS_CHECK_BASE_TYPE
+#define LANG_HOOKS_CHECK_BASE_TYPE cp_check_base_type
 #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
 #define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
 #undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
--- gcc/cp/cp-objcp-common.c.jj	2016-11-01 14:39:29.308309164 +0100
+++ gcc/cp/cp-objcp-common.c	2016-11-01 14:22:40.135992547 +0100
@@ -179,11 +179,6 @@ cp_decl_dwarf_attribute (const_tree decl
 	  && FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
 	  && !FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
 	return 1;
-      if ((TREE_CODE (decl) == FUNCTION_TYPE
-	   || TREE_CODE (decl) == METHOD_TYPE)
-	  && FUNCTION_REF_QUALIFIED (decl)
-	  && !FUNCTION_RVALUE_QUALIFIED (decl))
-	return 1;
       break;
 
     case DW_AT_rvalue_reference:
@@ -192,11 +187,6 @@ cp_decl_dwarf_attribute (const_tree decl
 	  && FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
 	  && FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
 	return 1;
-      if ((TREE_CODE (decl) == FUNCTION_TYPE
-	   || TREE_CODE (decl) == METHOD_TYPE)
-	  && FUNCTION_REF_QUALIFIED (decl)
-	  && FUNCTION_RVALUE_QUALIFIED (decl))
-	return 1;
       break;
 
     case DW_AT_inline:
@@ -216,6 +206,57 @@ cp_decl_dwarf_attribute (const_tree decl
   return -1;
 }
 
+/* Return -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+   value otherwise.  */
+int
+cp_type_dwarf_attribute (const_tree type, int attr)
+{
+  if (type == NULL_TREE)
+    return -1;
+
+  switch (attr)
+    {
+    case DW_AT_reference:
+      if ((TREE_CODE (type) == FUNCTION_TYPE
+	   || TREE_CODE (type) == METHOD_TYPE)
+	  && FUNCTION_REF_QUALIFIED (type)
+	  && !FUNCTION_RVALUE_QUALIFIED (type))
+	return 1;
+      break;
+
+    case DW_AT_rvalue_reference:
+      if ((TREE_CODE (type) == FUNCTION_TYPE
+	   || TREE_CODE (type) == METHOD_TYPE)
+	  && FUNCTION_REF_QUALIFIED (type)
+	  && FUNCTION_RVALUE_QUALIFIED (type))
+	return 1;
+      break;
+
+    default:
+      break;
+    }
+
+  return -1;
+}
+
+/* Perform any FE specific additional testing whether
+   CAND and BASE are the same type for except for get_qualified_type
+   purposes.  */
+
+bool
+cp_check_base_type (const_tree cand, const_tree base)
+{
+  if (TREE_CODE (cand) == FUNCTION_TYPE
+      || TREE_CODE (cand) == METHOD_TYPE)
+    {
+      gcc_assert (TREE_CODE (base) == FUNCTION_TYPE
+		  || TREE_CODE (base) == METHOD_TYPE);
+      if (type_memfn_rqual (cand) != type_memfn_rqual (base))
+	return false;
+    }
+  return true;
+}
+
 /* Stubs to keep c-opts.c happy.  */
 void
 push_file_scope (void)
--- gcc/hooks.c.jj	2016-10-31 13:28:06.000000000 +0100
+++ gcc/hooks.c	2016-11-01 12:55:58.479182864 +0100
@@ -293,6 +293,12 @@ hook_bool_tree_tree_true (tree, tree)
 }
 
 bool
+hook_bool_const_tree_const_tree_true (const_tree, const_tree)
+{
+  return true;
+}
+
+bool
 hook_bool_tree_bool_false (tree, bool)
 {
   return false;
--- gcc/dwarf2out.c.jj	2016-11-01 12:27:57.000000000 +0100
+++ gcc/dwarf2out.c	2016-11-01 14:12:07.533930429 +0100
@@ -12569,8 +12569,19 @@ modified_type_die (tree type, int cv_qua
 	 copy was created to help us keep track of typedef names) and
 	 that copy might have a different TYPE_UID from the original
 	 ..._TYPE node.  */
-      if (TREE_CODE (type) != VECTOR_TYPE
-	  && TREE_CODE (type) != ARRAY_TYPE)
+      if (TREE_CODE (type) == FUNCTION_TYPE
+	  || TREE_CODE (type) == METHOD_TYPE)
+	{
+	  /* For function/method types, can't use type_main_variant here,
+	     because that can have different ref-qualifiers for C++,
+	     but try to canonicalize.  */
+	  for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+	    if (check_qualified_type (t, type, TYPE_QUALS (type)))
+	      type = t;
+	  return lookup_type_die (type);
+	}
+      else if (TREE_CODE (type) != VECTOR_TYPE
+	       && TREE_CODE (type) != ARRAY_TYPE)
 	return lookup_type_die (type_main_variant (type));
       else
 	/* Vectors have the debugging information in the type,
@@ -24054,6 +24065,13 @@ gen_subroutine_type_die (tree type, dw_d
 
   if (get_AT (subr_die, DW_AT_name))
     add_pubtype (type, subr_die);
+  if ((dwarf_version >= 5 || !dwarf_strict)
+      && lang_hooks.types.type_dwarf_attribute (type, DW_AT_reference) != -1)
+    add_AT_flag (subr_die, DW_AT_reference, 1);
+  if ((dwarf_version >= 5 || !dwarf_strict)
+      && lang_hooks.types.type_dwarf_attribute (type,
+						DW_AT_rvalue_reference) != -1)
+    add_AT_flag (subr_die, DW_AT_rvalue_reference, 1);
 }
 
 /* Generate a DIE for a type definition.  */
@@ -24279,9 +24297,20 @@ gen_type_die_with_usage (tree type, dw_d
      of this type (i.e. without any const or volatile qualifiers) so
      get the main variant (i.e. the unqualified version) of this type
      now.  (Vectors and arrays are special because the debugging info is in the
-     cloned type itself).  */
-  if (TREE_CODE (type) != VECTOR_TYPE
-      && TREE_CODE (type) != ARRAY_TYPE)
+     cloned type itself.  Similarly function/method types can contain extra
+     ref-qualification).  */
+  if (TREE_CODE (type) == FUNCTION_TYPE
+      || TREE_CODE (type) == METHOD_TYPE)
+    {
+      /* For function/method types, can't use type_main_variant here,
+	 because that can have different ref-qualifiers for C++,
+	 but try to canonicalize.  */
+      for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+	if (check_qualified_type (t, type, TYPE_QUALS (type)))
+	  type = t;
+    }
+  else if (TREE_CODE (type) != VECTOR_TYPE
+	   && TREE_CODE (type) != ARRAY_TYPE)
     type = type_main_variant (type);
 
   /* If this is an array type with hidden descriptor, handle it first.  */
@@ -24353,14 +24382,14 @@ gen_type_die_with_usage (tree type, dw_d
     case FUNCTION_TYPE:
       /* Force out return type (in case it wasn't forced out already).  */
       gen_type_die_with_usage (TREE_TYPE (type), context_die,
-					DINFO_USAGE_DIR_USE);
+			       DINFO_USAGE_DIR_USE);
       gen_subroutine_type_die (type, context_die);
       break;
 
     case METHOD_TYPE:
       /* Force out return type (in case it wasn't forced out already).  */
       gen_type_die_with_usage (TREE_TYPE (type), context_die,
-					DINFO_USAGE_DIR_USE);
+			       DINFO_USAGE_DIR_USE);
       gen_subroutine_type_die (type, context_die);
       break;
 
--- gcc/langhooks-def.h.jj	2016-10-31 13:28:13.000000000 +0100
+++ gcc/langhooks-def.h	2016-11-01 13:29:15.299138536 +0100
@@ -84,6 +84,7 @@ extern bool lhd_omp_mappable_type (tree)
 extern const char *lhd_get_substring_location (const substring_loc &,
 					       location_t *out_loc);
 extern int lhd_decl_dwarf_attribute (const_tree, int);
+extern int lhd_type_dwarf_attribute (const_tree, int);
 
 #define LANG_HOOKS_NAME			"GNU unknown"
 #define LANG_HOOKS_IDENTIFIER_SIZE	sizeof (struct lang_identifier)
@@ -186,6 +187,8 @@ extern tree lhd_make_node (enum tree_cod
 #define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE lhd_enum_underlying_base_type
 #define LANG_HOOKS_GET_DEBUG_TYPE	NULL
 #define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO NULL
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE	lhd_type_dwarf_attribute
+#define LANG_HOOKS_CHECK_BASE_TYPE	hook_bool_const_tree_const_tree_true
 
 #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
   LANG_HOOKS_MAKE_TYPE, \
@@ -208,7 +211,9 @@ extern tree lhd_make_node (enum tree_cod
   LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
   LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE, \
   LANG_HOOKS_GET_DEBUG_TYPE, \
-  LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO \
+  LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
+  LANG_HOOKS_TYPE_DWARF_ATTRIBUTE, \
+  LANG_HOOKS_CHECK_BASE_TYPE \
 }
 
 /* Declaration hooks.  */
--- gcc/langhooks.h.jj	2016-10-31 16:42:21.349663774 +0100
+++ gcc/langhooks.h	2016-11-01 12:49:31.618038408 +0100
@@ -162,6 +162,14 @@ struct lang_hooks_for_types
      for the debugger about scale factor, etc.  */
   bool (*get_fixed_point_type_info) (const_tree,
 				     struct fixed_point_type_info *);
+
+  /* Returns -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+     value otherwise.  */
+  int (*type_dwarf_attribute) (const_tree, int);
+
+  /* Return TRUE iff unqualified CAND and BASE types are equivalent for
+     check_qualified_type purposes.  */
+  bool (*check_base_type) (const_tree, const_tree);
 };
 
 /* Language hooks related to decls and the symbol table.  */
--- gcc/tree.c.jj	2016-10-31 16:42:21.348663787 +0100
+++ gcc/tree.c	2016-11-01 12:49:31.622038358 +0100
@@ -6507,6 +6507,7 @@ check_base_type (const_tree cand, const_
 	  && TYPE_CONTEXT (cand) == TYPE_CONTEXT (base)
 	  /* Check alignment.  */
 	  && TYPE_ALIGN (cand) == TYPE_ALIGN (base)
+	  && lang_hooks.types.check_base_type (cand, base)
 	  && attribute_list_equal (TYPE_ATTRIBUTES (cand),
 				   TYPE_ATTRIBUTES (base)));
 }
--- gcc/langhooks.c.jj	2016-10-31 13:28:11.000000000 +0100
+++ gcc/langhooks.c	2016-11-01 12:53:22.330142711 +0100
@@ -702,6 +702,15 @@ lhd_decl_dwarf_attribute (const_tree, in
   return -1;
 }
 
+/* Default implementation of LANG_HOOKS_TYPE_DWARF_ATTRIBUTE.  Don't add
+   any attributes.  */
+
+int
+lhd_type_dwarf_attribute (const_tree, int)
+{
+  return -1;
+}
+
 /* Returns true if the current lang_hooks represents the GNU C frontend.  */
 
 bool


	Jakub


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