I am trying to get more useful warnings for array bounds.
In particular I am interested in cases like this:

void foo(int (*a)[3], int n, int (*b)[n])
{
        (*a)[4] = 1;
        (*b)[n + 1] = 1;
}

That currently even the first assignment does not produce a warning
is a bit disappointing. (clang does)

There is also no warning in the following example
when the array is the last element of a struct.

struct h3 {
        int i;
        int j[3];
};

struct h3* h3 = malloc(sizeof(struct h) + 3 * sizeof(int));
h3->j[4] = 1;

I guess this is to avoid warnings for the 'struct hack', but why 
is this not limited to arrays with size 0 (and maybe 1) and 
flexible array members?

The relevant code is in the function check_array_ref in 
gcc/tree-vrp.c (see below). It seems that this code accidentally 
deactivates all warnings for arrays accessed through a pointer. 
Or is there a reason for returning when this is not a struct member?

It also gives arrays which are the last member of a struct a free
pass - even if they have a size greater than 1.

Martin



 
  /* Accesses to trailing arrays via pointers may access storage
     beyond the types array bounds.  */
  base = get_base_address (ref);
  if (base && TREE_CODE (base) == MEM_REF)
    {
      tree cref, next = NULL_TREE;

      if (TREE_CODE (TREE_OPERAND (ref, 0)) != COMPONENT_REF)
        return;

      cref = TREE_OPERAND (ref, 0);
      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (cref, 0))) == RECORD_TYPE)
        for (next = DECL_CHAIN (TREE_OPERAND (cref, 1));
             next && TREE_CODE (next) != FIELD_DECL;
             next = DECL_CHAIN (next))
          ;

      /* If this is the last field in a struct type or a field in a
         union type do not warn.  */
      if (!next)
        return;
    }

Reply via email to