On Fri, 15 Mar 2019, Jason Merrill wrote:

> On 3/15/19 9:33 AM, Richard Biener wrote:
> > 
> > The following is an attempt to fix PR71598 where C (and C++?) have
> > an implementation-defined compatible integer type for each enum
> > and the TBAA rules mandate that accesses using a compatible type
> > are allowed.
> 
> This does not apply to C++; an enum does not alias its underlying type.

Thus the following different patch, introducing c_get_alias_set and
only doing the special handling for C family frontends (I assume
that at least ObjC is also affected).

Bootstrap & regtest running on x86_64-unknown-linux-gnu, OK?

Thanks,
Richard.

2019-03-18  Richard Biener  <rguent...@suse.de>

        PR c/71598
        * gimple.c: Include langhooks.h.
        (gimple_get_alias_set): Treat enumeral types as the underlying
        integer type.

        c/
        * c-tree.h (c_get_alias_set): Declare.
        * c-objc-common.h (LANG_HOOKS_GET_ALIAS_SET): Use c_get_alias_set.
        * c-objc-common.c (c_get_alias_set): Treat enumeral types
        as the underlying integer type.

        * gcc.dg/torture/pr71598-1.c: New testcase.
        * gcc.dg/torture/pr71598-2.c: Likewise.


Index: gcc/c/c-objc-common.c
===================================================================
--- gcc/c/c-objc-common.c       (revision 269752)
+++ gcc/c/c-objc-common.c       (working copy)
@@ -265,3 +265,22 @@ c_vla_unspec_p (tree x, tree fn ATTRIBUT
 {
   return c_vla_type_p (x);
 }
+
+/* Special routine to get the alias set of T for C.  */
+
+alias_set_type
+c_get_alias_set (tree t)
+{
+  /* Allow aliasing between enumeral types and the underlying
+     integer type.  This is required since those are compatible types.  */
+  if (TREE_CODE (t) == ENUMERAL_TYPE)
+    {
+      tree t1 = c_common_type_for_size (tree_to_uhwi (TYPE_SIZE (t)),
+                                       /* short-cut commoning to signed
+                                          type.  */
+                                       false);
+      return get_alias_set (t1);
+    }
+
+  return c_common_get_alias_set (t);
+}
Index: gcc/c/c-objc-common.h
===================================================================
--- gcc/c/c-objc-common.h       (revision 269752)
+++ gcc/c/c-objc-common.h       (working copy)
@@ -43,7 +43,7 @@ along with GCC; see the file COPYING3.
 #undef LANG_HOOKS_POST_OPTIONS
 #define LANG_HOOKS_POST_OPTIONS c_common_post_options
 #undef LANG_HOOKS_GET_ALIAS_SET
-#define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
+#define LANG_HOOKS_GET_ALIAS_SET c_get_alias_set
 #undef LANG_HOOKS_PARSE_FILE
 #define LANG_HOOKS_PARSE_FILE c_common_parse_file
 #undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
Index: gcc/c/c-tree.h
===================================================================
--- gcc/c/c-tree.h      (revision 269752)
+++ gcc/c/c-tree.h      (working copy)
@@ -623,6 +623,7 @@ extern bool c_missing_noreturn_ok_p (tre
 extern bool c_warn_unused_global_decl (const_tree);
 extern void c_initialize_diagnostics (diagnostic_context *);
 extern bool c_vla_unspec_p (tree x, tree fn);
+extern alias_set_type c_get_alias_set (tree);
 
 /* in c-typeck.c */
 extern int in_alignof;
Index: gcc/gimple.c
===================================================================
--- gcc/gimple.c        (revision 269752)
+++ gcc/gimple.c        (working copy)
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3.
 #include "stringpool.h"
 #include "attribs.h"
 #include "asan.h"
+#include "langhooks.h"
 
 
 /* All the tuples have their operand vector (if present) at the very bottom
@@ -2587,6 +2588,16 @@ gimple_get_alias_set (tree t)
        return get_alias_set (t1);
     }
 
+  /* Allow aliasing between enumeral types and the underlying
+     integer type.  This is required for C since those are
+     compatible types.  */
+  else if (TREE_CODE (t) == ENUMERAL_TYPE)
+    {
+      tree t1 = lang_hooks.types.type_for_size (tree_to_uhwi (TYPE_SIZE (t)),
+                                               false /* short-cut above */);
+      return get_alias_set (t1);
+    }
+
   return -1;
 }
 
Index: gcc/testsuite/gcc.dg/torture/pr71598-1.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr71598-1.c    (nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr71598-1.c    (working copy)
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fno-short-enums" } */
+
+enum e1 { c1 };
+
+__attribute__((noinline,noclone))
+int f(enum e1 *p, unsigned *q)
+{
+  *p = c1;
+  *q = 2;
+  return *p;
+}
+
+int main()
+{
+  unsigned x;
+
+  if (f(&x, &x) != 2)
+    __builtin_abort();
+  return 0;
+}
Index: gcc/testsuite/gcc.dg/torture/pr71598-2.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr71598-2.c    (nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr71598-2.c    (working copy)
@@ -0,0 +1,47 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fshort-enums" } */
+
+enum e1 { c1 = -__INT_MAX__ };
+
+__attribute__((noinline,noclone))
+int f(enum e1 *p, signed int *q)
+{
+  *p = c1;
+  *q = 2;
+  return *p;
+}
+
+enum e2 { c2 = __SHRT_MAX__ + 1};
+
+__attribute__((noinline,noclone))
+int g(enum e2 *p, unsigned short *q)
+{
+  *p = c2;
+  *q = 2;
+  return *p;
+}
+
+enum e3 { c3 = __SCHAR_MAX__ };
+
+__attribute__((noinline,noclone))
+int h(enum e3 *p, unsigned char *q)
+{
+  *p = c3;
+  *q = 2;
+  return *p;
+}
+
+int main()
+{
+  signed x;
+  unsigned short y;
+  unsigned char z;
+
+  if (f(&x, &x) != 2)
+    __builtin_abort();
+  if (g(&y, &y) != 2)
+    __builtin_abort();
+  if (h(&z, &z) != 2)
+    __builtin_abort();
+  return 0;
+}

Reply via email to