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] preserve DECL_ORIGINAL_TYPE invariant in remap_decl


Hi,

the invariant is that DECL_ORIGINAL_TYPE (t) != TREE_TYPE (t) as pointer value 
if t is a TYPE_DECL.  It's enforced by the DWARF back-end:

      if (DECL_ORIGINAL_TYPE (decl))
	{
	  type = DECL_ORIGINAL_TYPE (decl);

	  if (type == error_mark_node)
	    return;

	  gcc_assert (type != TREE_TYPE (decl));

[...]

      /* Prevent broken recursion; we can't hand off to the same type.  */
      gcc_assert (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) != type);

Unfortunately it can be easily broken in remap_decl:

      /* Remap types, if necessary.  */
      TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
      if (TREE_CODE (t) == TYPE_DECL)
        DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id);

If TREE_TYPE (t) is for example a pointer to a variably-modified type, then 
the types are remapped by means of build_pointer_type_for_mode, which means 
that they are also canonicalized, so TREE_TYPE (t) == DECL_ORIGINAL_TYPE (t) 
after the remapping.  This happens in Ada, but also in C for:

extern void bar (void *) __attribute__((noreturn));

static int foo (int i, unsigned int n)
{
  if (i == 0)
    {
      struct S { int a[n]; };
      typedef struct S *ptr;
      ptr p = __builtin_malloc (sizeof (struct S));
      bar (p);
    }

  return i > 0 ? 1 : -1;
}

int f1 (int i, unsigned int n)
{
  return foo (i, n);
}

int f2 (int i, unsigned int n)
{
  return foo (i, n);
}

when foo is split into 2 parts at -O2.

This generally goes unnoticed because the inliner sets DECL_ABSTRACT_ORIGIN on 
the remapped TYPE_DECL, so gen_typedef_die skips it:

  type_die = new_die (DW_TAG_typedef, context_die, decl);
  origin = decl_ultimate_origin (decl);
  if (origin != NULL)
    add_abstract_origin_attribute (type_die, origin);
  else
    {
      tree type;

      add_name_and_src_coords_attributes (type_die, decl);
      if (DECL_ORIGINAL_TYPE (decl))
	{
	  type = DECL_ORIGINAL_TYPE (decl);

	  if (type == error_mark_node)
	    return;

	  gcc_assert (type != TREE_TYPE (decl));
	  equate_type_number_to_die (TREE_TYPE (decl), type_die);
	}

But, in LTO mode, DECL_ABSTRACT_ORIGIN is not streamed so it's another story 
and this for example breaks the LTO build of the Ada compiler at -O2 -g.

Hence the attached ad-hoc attempt at preserving the invariant in remap_decl, 
which appears to work and is sufficient to fix the aforementioned bootstrap.

Tested on x86_64-suse-linux, OK for the mainline?


2016-06-22  Eric Botcazou  <ebotcazou@adacore.com>

	* tree-inline.c (remap_decl): Preserve DECL_ORIGINAL_TYPE invariant.

-- 
Eric Botcazou
Index: tree-inline.c
===================================================================
--- tree-inline.c	(revision 237677)
+++ tree-inline.c	(working copy)
@@ -367,7 +367,18 @@ remap_decl (tree decl, copy_body_data *i
       /* Remap types, if necessary.  */
       TREE_TYPE (t) = remap_type (TREE_TYPE (t), id);
       if (TREE_CODE (t) == TYPE_DECL)
-        DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id);
+	{
+	  DECL_ORIGINAL_TYPE (t) = remap_type (DECL_ORIGINAL_TYPE (t), id);
+
+	  /* Preserve the invariant that DECL_ORIGINAL_TYPE != TREE_TYPE.  */
+	  if (DECL_ORIGINAL_TYPE (t) == TREE_TYPE (t))
+	    {
+	      tree x = build_variant_type_copy (TREE_TYPE (t));
+	      TYPE_STUB_DECL (x) = TYPE_STUB_DECL (TREE_TYPE (t));
+	      TYPE_NAME (x) = t;
+	      DECL_ORIGINAL_TYPE (t) = x;
+	    }
+	}
 
       /* Remap sizes as necessary.  */
       walk_tree (&DECL_SIZE (t), copy_tree_body_r, id, NULL);

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