diff mbox

Add a new type attribute always_alias (PR79671)

Message ID AM4PR0701MB21623337A5C0C1850D3DF4C7E40A0@AM4PR0701MB2162.eurprd07.prod.outlook.com
State New
Headers show

Commit Message

Bernd Edlinger April 5, 2017, 9:02 p.m. UTC
On 04/05/17 19:22, Bernd Edlinger wrote:
> On 04/05/17 18:08, Jakub Jelinek wrote:
>
> Yes, exactly.  I really want to reach the deadline for gcc-7.
> Fixing the name is certainly the most important first step,
> and if everybody agrees on "typeless_storage", for the name
> I can start with adjusting the name, and look into how
> to use a spare type-flag that should be a mechanical change.
>

Jakub, I just renamed the attribute and reworked the patch
as you suggested, reg-testing is not yet completed, but
it looks good so far.  I also added a few more tests.

I have changed the documentation as Richi suggested, but
I am not too sure what to say here.


Thanks
Bernd.
gcc
2017-04-05  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* doc/extend.texi: Document the typeless_storage type attribute.
	* alias.c (get_alias_set): Honor the typeless_storage attribute.
	(record_component_aliases): Don't ignore the typeless_storage
	attribute.
	* tree.c (build_pointer_type_for_mode,
	build_reference_type_for_mode): Handle the typeless_storage
	attribute.
	* print-tree.c (print_node): Likewise.
	* tree-streamer-in.c (unpack_ts_type_common_value_fields): Likewise.
	* tree-streamer-out.c (pack_ts_type_common_value_fields): Likewise.
	* tre.h (TYPE_TYPELESS_STORAGE): New access macro.
	* tree-core.h (tree_type_common::typeless_storage_flag): New flag.

gcc/c-family
2017-04-05  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* c-attribs.c (c_common_attribute_tab): Add the typeless_storage
	attribute.
	(handle_typeless_storage_attribute): New function.

gcc/cp
2017-04-05  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* class.c (fixup_attribute_variants): Handle the typeless_storage
	attribute.
	(finish_struct_1): Set the typeless_storage attribute if required
	by C++17.
	* decl.c (start_enum): Likewise.
	* pt.c (lookup_template_class_1): Handle the typeless_storage
	attribute.
	* typeck2.c (cxx_type_contains_byte_buffer): New function.
	* cp-tree.h (cxx_type_contains_byte_buffer): Declare.

gcc/lto
2017-04-05  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* lto.c (compare_tree_sccs_1, hash_tree): Handle the typeless_storage
	attribute.

gcc/testsuite
2017-04-05  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* c-c++-common/attr-typeless-storage-1.c: New test.
	* c-c++-common/attr-typeless-storage-2.c: New test.
	* gcc.c-torture/execute/typeless-storage-1.c: New test.

Comments

Sandra Loosemore April 5, 2017, 11:17 p.m. UTC | #1
On 04/05/2017 03:02 PM, Bernd Edlinger wrote:
> On 04/05/17 19:22, Bernd Edlinger wrote:
>> On 04/05/17 18:08, Jakub Jelinek wrote:
>>
>> Yes, exactly.  I really want to reach the deadline for gcc-7.
>> Fixing the name is certainly the most important first step,
>> and if everybody agrees on "typeless_storage", for the name
>> I can start with adjusting the name, and look into how
>> to use a spare type-flag that should be a mechanical change.
>>
>
> Jakub, I just renamed the attribute and reworked the patch
> as you suggested, reg-testing is not yet completed, but
> it looks good so far.  I also added a few more tests.
>
> I have changed the documentation as Richi suggested, but
> I am not too sure what to say here.
>

> Index: gcc/doc/extend.texi
> ===================================================================
> --- gcc/doc/extend.texi	(revision 246678)
> +++ gcc/doc/extend.texi	(working copy)
> @@ -6656,6 +6656,11 @@ declaration, the above program would abort when co
>  @option{-fstrict-aliasing}, which is on by default at @option{-O2} or
>  above.
>
> +@item typeless_storage
> +@cindex @code{typeless_storage} type attribute
> +An object declared with a type with this attribute behaves like a
> +character type with respect to aliasing semantics.
> +
>  @item packed
>  @cindex @code{packed} type attribute
>  This attribute, attached to @code{struct} or @code{union} type


"An object ....  behaves like a character type"?  I think you mean "as 
if it had character type".  Or maybe something simpler like "A type 
declared with this attribute has the same aliasing semantics as 
@code{char} type."

-Sandra
Jakub Jelinek April 6, 2017, 5:40 a.m. UTC | #2
On Wed, Apr 05, 2017 at 05:17:24PM -0600, Sandra Loosemore wrote:
> > > Yes, exactly.  I really want to reach the deadline for gcc-7.
> > > Fixing the name is certainly the most important first step,
> > > and if everybody agrees on "typeless_storage", for the name
> > > I can start with adjusting the name, and look into how
> > > to use a spare type-flag that should be a mechanical change.
> > > 
> > 
> > Jakub, I just renamed the attribute and reworked the patch
> > as you suggested, reg-testing is not yet completed, but
> > it looks good so far.  I also added a few more tests.
> > 
> > I have changed the documentation as Richi suggested, but
> > I am not too sure what to say here.
> > 
> 
> > Index: gcc/doc/extend.texi
> > ===================================================================
> > --- gcc/doc/extend.texi	(revision 246678)
> > +++ gcc/doc/extend.texi	(working copy)
> > @@ -6656,6 +6656,11 @@ declaration, the above program would abort when co
> >  @option{-fstrict-aliasing}, which is on by default at @option{-O2} or
> >  above.
> > 
> > +@item typeless_storage
> > +@cindex @code{typeless_storage} type attribute
> > +An object declared with a type with this attribute behaves like a
> > +character type with respect to aliasing semantics.
> > +
> >  @item packed
> >  @cindex @code{packed} type attribute
> >  This attribute, attached to @code{struct} or @code{union} type
> 
> 
> "An object ....  behaves like a character type"?  I think you mean "as if it
> had character type".  Or maybe something simpler like "A type declared with
> this attribute has the same aliasing semantics as @code{char} type."

Well, that wording doesn't make much sense, because the problem is exactly
that alias semantics of the char type does not do what C++ needs from
unsigned char [N] or std::byte [N] arrays.  char type inside of a structure
no longer means you can put anything in there.  If you have effective type
of char and access it through lvalue of some type incompatible with it (see
the C99 6.5/7 rules), then it is still invalid, only if you access object
of any effective type through lvalue of char type, then it is valid.
Now, for objects with type with typeless_storage or for C++ unsigned char
or std::byte arrays, we basically want to say that accessing them through
lvalue of any type is well defined.  I'd probably document it just for
typeless_storage attribute, because for the unsigned char and std::byte
arrays it is C++17 that defines the exact rules and they are probably
less strict than that, so it would be good if we leave it open to refine
the unsigned char/std::byte array behavior later on to better match what
C++ requires.  Not sure if we want to document anything about accesses
through lvalue of type with typeless_storage attribute, whether that also
implies it is like accesses through lvalue of type char.  If yes, that
would be may_alias attribute behavior extended, so that it is not just
accesses through pointers/references to type with may_alias attribute
that are treated that way, but any accesses through lvalue with type
with typeless_storage attribute.

	Jakub
diff mbox

Patch

Index: gcc/alias.c
===================================================================
--- gcc/alias.c	(revision 246678)
+++ gcc/alias.c	(working copy)
@@ -879,6 +879,10 @@  get_alias_set (tree t)
       t = TREE_TYPE (t);
     }
 
+  /* Honor the typeless_storage type attribute.  */
+  if (TYPE_TYPELESS_STORAGE (t))
+    return 0;
+
   /* Variant qualifiers don't affect the alias set, so get the main
      variant.  */
   t = TYPE_MAIN_VARIANT (t);
@@ -1234,7 +1238,8 @@  record_component_aliases (tree type)
 		/* VECTOR_TYPE and ARRAY_TYPE share the alias set with their
 		   element type and that type has to be normalized to void *,
 		   too, in the case it is a pointer. */
-		while (!canonical_type_used_p (t) && !POINTER_TYPE_P (t))
+		while (!canonical_type_used_p (t) && !POINTER_TYPE_P (t)
+		       && !TYPE_TYPELESS_STORAGE (t))
 		  {
 		    gcc_checking_assert (TYPE_STRUCTURAL_EQUALITY_P (t));
 		    t = TREE_TYPE (t);
Index: gcc/c-family/c-attribs.c
===================================================================
--- gcc/c-family/c-attribs.c	(revision 246678)
+++ gcc/c-family/c-attribs.c	(working copy)
@@ -113,6 +113,7 @@  static tree handle_vector_size_attribute (tree *,
 					  bool *);
 static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
+static tree handle_typeless_storage_attribute (tree *, tree, tree, int, bool *);
 static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
 static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
 						 bool *);
@@ -265,6 +266,8 @@  const struct attribute_spec c_common_attribute_tab
   { "nothrow",                0, 0, true,  false, false,
 			      handle_nothrow_attribute, false },
   { "may_alias",	      0, 0, false, true, false, NULL, false },
+  { "typeless_storage",       0, 0, false, true, false,
+			      handle_typeless_storage_attribute, false },
   { "cleanup",		      1, 1, true, false, false,
 			      handle_cleanup_attribute, false },
   { "warn_unused_result",     0, 0, false, true, true,
@@ -2879,6 +2882,24 @@  handle_nothrow_attribute (tree *node, tree name, t
   return NULL_TREE;
 }
 
+/* Handle a "typeless_storage" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_typeless_storage_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+				   int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TYPE_P (*node))
+    TYPE_TYPELESS_STORAGE (*node) = 1;
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "cleanup" attribute; arguments as in
    struct attribute_spec.handler.  */
 
Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c	(revision 246678)
+++ gcc/cp/class.c	(working copy)
@@ -2083,7 +2083,8 @@  fixup_attribute_variants (tree t)
   tree attrs = TYPE_ATTRIBUTES (t);
   unsigned align = TYPE_ALIGN (t);
   bool user_align = TYPE_USER_ALIGN (t);
-  bool may_alias = lookup_attribute ("may_alias", attrs);
+  bool may_alias = TYPE_TYPELESS_STORAGE (t)
+		   || lookup_attribute ("may_alias", attrs);
 
   if (may_alias)
     fixup_may_alias (t);
@@ -7345,6 +7348,12 @@  finish_struct_1 (tree t)
      the class or perform any other required target modifications.  */
   targetm.cxx.adjust_class_at_definition (t);
 
+  if (cxx_dialect >= cxx1z && cxx_type_contains_byte_buffer (t))
+    {
+      TYPE_TYPELESS_STORAGE (t) = 1;
+      fixup_attribute_variants (t);
+    }
+
   maybe_suppress_debug_info (t);
 
   if (flag_vtable_verify)
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 246678)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -6858,6 +6858,7 @@  extern tree finish_binary_fold_expr          (tree
 extern void require_complete_eh_spec_types	(tree, tree);
 extern void cxx_incomplete_type_diagnostic	(location_t, const_tree,
 						 const_tree, diagnostic_t);
+extern bool cxx_type_contains_byte_buffer	(tree);
 inline void
 cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
 				diagnostic_t diag_kind)
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 246678)
+++ gcc/cp/decl.c	(working copy)
@@ -14081,10 +14081,11 @@  start_enum (tree name, tree enumtype, tree underly
 	  enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
 
 	  /* std::byte aliases anything.  */
-	  if (enumtype != error_mark_node
+	  if (cxx_dialect >= cxx1z
+	      && enumtype != error_mark_node
 	      && TYPE_CONTEXT (enumtype) == std_node
 	      && !strcmp ("byte", TYPE_NAME_STRING (enumtype)))
-	    TYPE_ALIAS_SET (enumtype) = 0;
+	    TYPE_TYPELESS_STORAGE (enumtype) = 1;
 	}
       else
 	  enumtype = xref_tag (enum_type, name, /*tag_scope=*/ts_current,
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 246678)
+++ gcc/cp/pt.c	(working copy)
@@ -8853,7 +8853,8 @@  lookup_template_class_1 (tree d1, tree arglist, tr
 	{
 	  static const char *tags[] = {"abi_tag", "may_alias"};
 
-	  for (unsigned ix = 0; ix != 2; ix++)
+	  TYPE_TYPELESS_STORAGE (t) |= TYPE_TYPELESS_STORAGE (template_type);
+	  for (unsigned ix = 0; ix < sizeof (tags) / sizeof (tags[0]); ix++)
 	    {
 	      tree attributes
 		= lookup_attribute (tags[ix], TYPE_ATTRIBUTES (template_type));
Index: gcc/cp/typeck2.c
===================================================================
--- gcc/cp/typeck2.c	(revision 246678)
+++ gcc/cp/typeck2.c	(working copy)
@@ -2234,5 +2234,29 @@  require_complete_eh_spec_types (tree fntype, tree
     }
 }
 
+/* True iff type either is or contains a byte buffer (which can be used for
+   storing any trivially copyable type).  */
+
+bool
+cxx_type_contains_byte_buffer (tree type)
+{
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && (cxx_type_contains_byte_buffer (TREE_TYPE (type))
+	  || TREE_TYPE (type) == unsigned_char_type_node
+	  || (TREE_CODE (TREE_TYPE (type)) == ENUMERAL_TYPE
+	      && TYPE_CONTEXT (TREE_TYPE (type)) == std_node
+	      && !strcmp ("byte", TYPE_NAME_STRING (TREE_TYPE (type))))))
+    return true;
+
+  if (CLASS_TYPE_P (type))
+    for (tree field = next_initializable_field (TYPE_FIELDS (type));
+	 field;
+	 field = next_initializable_field (DECL_CHAIN (field)))
+      if (cxx_type_contains_byte_buffer (TREE_TYPE (field)))
+	return true;
+
+  return false;
+}
+
 
 #include "gt-cp-typeck2.h"
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 246678)
+++ gcc/doc/extend.texi	(working copy)
@@ -6656,6 +6656,11 @@  declaration, the above program would abort when co
 @option{-fstrict-aliasing}, which is on by default at @option{-O2} or
 above.
 
+@item typeless_storage
+@cindex @code{typeless_storage} type attribute
+An object declared with a type with this attribute behaves like a
+character type with respect to aliasing semantics.
+
 @item packed
 @cindex @code{packed} type attribute
 This attribute, attached to @code{struct} or @code{union} type
Index: gcc/lto/lto.c
===================================================================
--- gcc/lto/lto.c	(revision 246678)
+++ gcc/lto/lto.c	(working copy)
@@ -1164,6 +1164,7 @@  compare_tree_sccs_1 (tree t1, tree t2, tree **map)
 	compare_values (TYPE_NONALIASED_COMPONENT);
       compare_values (TYPE_PACKED);
       compare_values (TYPE_RESTRICT);
+      compare_values (TYPE_TYPELESS_STORAGE);
       compare_values (TYPE_USER_ALIGN);
       compare_values (TYPE_READONLY);
       compare_values (TYPE_PRECISION);
Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c	(revision 246678)
+++ gcc/lto-streamer-out.c	(working copy)
@@ -1134,6 +1134,7 @@  hash_tree (struct streamer_tree_cache_d *cache, ha
       hstate.add_flag (TYPE_NEEDS_CONSTRUCTING (t));
       hstate.add_flag (TYPE_PACKED (t));
       hstate.add_flag (TYPE_RESTRICT (t));
+      hstate.add_flag (TYPE_TYPELESS_STORAGE (t));
       hstate.add_flag (TYPE_USER_ALIGN (t));
       hstate.add_flag (TYPE_READONLY (t));
       if (RECORD_OR_UNION_TYPE_P (t))
Index: gcc/print-tree.c
===================================================================
--- gcc/print-tree.c	(revision 246678)
+++ gcc/print-tree.c	(working copy)
@@ -574,6 +574,9 @@  print_node (FILE *file, const char *prefix, tree n
       if (TYPE_RESTRICT (node))
 	fputs (" restrict", file);
 
+      if (TYPE_TYPELESS_STORAGE (node))
+	fputs (" typeless-storage", file);
+
       if (TYPE_LANG_FLAG_0 (node))
 	fputs (" type_0", file);
       if (TYPE_LANG_FLAG_1 (node))
Index: gcc/testsuite/c-c++-common/attr-typeless-storage-1.c
===================================================================
--- gcc/testsuite/c-c++-common/attr-typeless-storage-1.c	(revision 0)
+++ gcc/testsuite/c-c++-common/attr-typeless-storage-1.c	(working copy)
@@ -0,0 +1,29 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wall" } */
+
+typedef int T __attribute__((typeless_storage));
+
+extern T t, v;
+extern T *p;
+extern int *p;
+
+extern int *p2;
+extern T *p2;
+
+void fn1 (T);
+void fn1 (int);
+
+void fn2 (int);
+void fn2 (T);
+
+/* Ensure that the composite types have typeless_storage.  */
+void
+f (long *i)
+{
+  *i = *(__typeof (*p) *) &p;
+  asm ("" : : "r" (*p));
+  *i = *(__typeof (*p2) *) &p2;
+  asm ("" : : "r" (*p2));
+  t = v;
+  asm ("" : : "r" (t));
+}
Index: gcc/testsuite/c-c++-common/attr-typeless-storage-2.c
===================================================================
--- gcc/testsuite/c-c++-common/attr-typeless-storage-2.c	(revision 0)
+++ gcc/testsuite/c-c++-common/attr-typeless-storage-2.c	(working copy)
@@ -0,0 +1,17 @@ 
+/* We used to reject this because types differentiating only in
+   TYPE_REF_CAN_ALIAS_ALL were deemed incompatible.  */
+/* { dg-do compile } */
+
+struct sockaddr;
+struct sockaddr *f (void);
+
+struct __attribute__((typeless_storage)) sockaddr { int j; };
+struct sockaddr *
+f (void)
+{
+  return
+#ifndef __cplusplus
+    (void *)
+#endif
+    0;
+}
Index: gcc/testsuite/gcc.c-torture/execute/typeless-storage-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/typeless-storage-1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/typeless-storage-1.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* Tests that the typeless_storage attribute works as expected.  */
+ 
+extern void abort(void);
+extern void exit(int);
+
+typedef int __attribute__((__typeless_storage__)) int_a;
+
+int
+main (void)
+{
+  int_a a = 0x12345678;
+  short *b = (short*) &a;
+
+  b[1] = 0;
+
+  if (a == 0x12345678)
+    abort();
+
+  exit(0);
+}
Index: gcc/tree-core.h
===================================================================
--- gcc/tree-core.h	(revision 246678)
+++ gcc/tree-core.h	(working copy)
@@ -1491,6 +1491,7 @@  struct GTY(()) tree_type_common {
   unsigned needs_constructing_flag : 1;
   unsigned transparent_aggr_flag : 1;
   unsigned restrict_flag : 1;
+  unsigned typeless_storage_flag : 1;
   unsigned contains_placeholder_bits : 2;
 
   ENUM_BITFIELD(machine_mode) mode : 8;
@@ -1511,7 +1512,7 @@  struct GTY(()) tree_type_common {
      so we need to store the value 32 (not 31, as we need the zero
      as well), hence six bits.  */
   unsigned align : 6;
-  unsigned spare : 25;
+  unsigned spare : 24;
   alias_set_type alias_set;
   tree pointer_to;
   tree reference_to;
Index: gcc/tree-streamer-in.c
===================================================================
--- gcc/tree-streamer-in.c	(revision 246678)
+++ gcc/tree-streamer-in.c	(working copy)
@@ -367,6 +367,7 @@  unpack_ts_type_common_value_fields (struct bitpack
   TYPE_NEEDS_CONSTRUCTING (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
+  TYPE_TYPELESS_STORAGE (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
   if (RECORD_OR_UNION_TYPE_P (expr))
Index: gcc/tree-streamer-out.c
===================================================================
--- gcc/tree-streamer-out.c	(revision 246678)
+++ gcc/tree-streamer-out.c	(working copy)
@@ -316,6 +316,7 @@  pack_ts_type_common_value_fields (struct bitpack_d
   bp_pack_value (bp, TYPE_NEEDS_CONSTRUCTING (expr), 1);
   bp_pack_value (bp, TYPE_PACKED (expr), 1);
   bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
+  bp_pack_value (bp, TYPE_TYPELESS_STORAGE (expr), 1);
   bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
   bp_pack_value (bp, TYPE_READONLY (expr), 1);
   /* We used to stream TYPE_ALIAS_SET == 0 information to let frontends mark
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 246678)
+++ gcc/tree.c	(working copy)
@@ -8041,7 +8041,8 @@  build_pointer_type_for_mode (tree to_type, machine
 
   /* If the pointed-to type has the may_alias attribute set, force
      a TYPE_REF_CAN_ALIAS_ALL pointer to be generated.  */
-  if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)))
+  if (TYPE_TYPELESS_STORAGE (to_type)
+      || lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)))
     can_alias_all = true;
 
   /* In some cases, languages will have things that aren't a POINTER_TYPE
@@ -8110,7 +8111,8 @@  build_reference_type_for_mode (tree to_type, machi
 
   /* If the pointed-to type has the may_alias attribute set, force
      a TYPE_REF_CAN_ALIAS_ALL pointer to be generated.  */
-  if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)))
+  if (TYPE_TYPELESS_STORAGE (to_type)
+      || lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)))
     can_alias_all = true;
 
   /* In some cases, languages will have things that aren't a REFERENCE_TYPE
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 246678)
+++ gcc/tree.h	(working copy)
@@ -1944,6 +1944,11 @@  extern machine_mode element_mode (const_tree t);
    the term.  */
 #define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type_common.restrict_flag)
 
+/* Nonzero if the type should behave like a character type
+   with respect to aliasing sementics.  */
+#define TYPE_TYPELESS_STORAGE(NODE) \
+  (TYPE_CHECK (NODE)->type_common.typeless_storage_flag)
+
 /* If nonzero, type's name shouldn't be emitted into debug info.  */
 #define TYPE_NAMELESS(NODE) (TYPE_CHECK (NODE)->base.u.bits.nameless_flag)