------- 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