[Bug c++/38699] [4.3/4.4/4.5 regression] ICE using offsetof with pointer and array accesses
dodji at redhat dot com
gcc-bugzilla@gcc.gnu.org
Wed Oct 28 15:42:00 GMT 2009
------- 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
More information about the Gcc-bugs
mailing list