------- Comment #10 from dodji at gcc dot gnu dot org  2009-10-28 15:42 -------
Subject: Re:  [4.3/4.4/4.5 regression] ICE using offsetof
        with pointer and array accesses

I am testing the patch below.

I am not sure the approach is the right one though. Comments welcome.

diff --git a/gcc/c-common.c b/gcc/c-common.c
index 8a6d15b..54e551f 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -8341,6 +8341,32 @@ fold_offsetof_1 (tree expr, tree stop_ref)

     case NOP_EXPR:
     case INDIRECT_REF:
+      if (TREE_CODE (expr) == INDIRECT_REF)
+       {
+         tree r = TREE_OPERAND (expr, 0);
+
+         if ((TREE_CODE (r) == NON_LVALUE_EXPR
+              && TREE_CODE (TREE_TYPE (r)) == POINTER_TYPE)
+             ||
+             (TREE_CODE (r) == POINTER_PLUS_EXPR))
+           {
+             /* We are trying something like:
+                struct A
+                {
+                  char *p;
+                };
+                void f ()
+                {
+                  __builtin_offsetof(struct A, p[1]);
+                }
+                But the C spec says that if t is of type A, then
+                 &(t.p[1])" should evaluate to a constant address.
+                 And &(t.p[1]) does not evaluate to a constant address here.
+                */
+             error ("cannot apply %<offsetof%> to a non constant address");
+             return error_mark_node;
+           }
+       }
       base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
       gcc_assert (base == error_mark_node || base == size_zero_node);
       return base;
@@ -8361,6 +8387,16 @@ fold_offsetof_1 (tree expr, tree stop_ref)
                            size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t),
                                                    1)
                                      / BITS_PER_UNIT));
+      /* Check if we the offset goes beyond the bound of the struct.  */
+      if (int_cst_value (off)
+         >= (int_cst_value (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (expr, 0))))
+             / BITS_PER_UNIT))
+       {
+         error_at (EXPR_LOCATION (t),
+                   "expression %qE denotes an offset greater than size of
%qT",
+                   t, TREE_TYPE (TREE_OPERAND (expr, 0)));
+         return error_mark_node;
+       }
       break;

     case ARRAY_REF:
@@ -8376,6 +8412,17 @@ fold_offsetof_1 (tree expr, tree stop_ref)
        }
       t = convert (sizetype, t);
       off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+
+      /* Check if we the indice of the array goes beyond the bound.  */
+      if (int_cst_value (off)
+         >= (int_cst_value (TYPE_SIZE (TREE_TYPE (TREE_OPERAND (expr, 0))))
+             / BITS_PER_UNIT))
+       {
+         error_at (EXPR_LOCATION (expr),
+                   "indice %ld denotes an offset greater than size of %qT",
+                   int_cst_value (t), TREE_TYPE (TREE_OPERAND (expr, 0)));
+         return error_mark_node;
+       }
       break;

     case COMPOUND_EXPR:


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38699

Reply via email to