blob: 172ec474c4287e55e2c401040cb1d1f09237161b [file] [log] [blame]
/* Further reduced container_of pattern from the Linux Kernel. */
struct inner {
/* Don't care */
};
struct outer {
int i;
struct inner inner_struct;
};
struct outer *container_of (struct inner *ptr_to_inner)
{
struct outer *ptr_to_outer = ((struct outer *) (((void *) ptr_to_inner) - __builtin_offsetof(struct outer, inner_struct)));
return ptr_to_outer;
}
int test (struct outer *outer_p, struct inner *inner_p)
{
struct outer test;
test.i = 42;
struct inner test2;
int sum = 0;
struct outer *o;
/* Symbolic inner struct. */
o = container_of (inner_p);
sum += o->i; // ok
/* Not ok, but we can't be sure that outer
is actually the container of inner. */
sum += (o - 1)->i;
/* Symbolic outer struct. */
o = container_of (&(outer_p->inner_struct));
sum += o->i; // ok
/* Not ok, but indistinguishable from the case above. */
sum += (o - 1)->i;
/* Concrete outer struct. */
o = container_of (&(test.inner_struct));
sum += o->i; // ok
/* Not ok and we do have a concrete region. */
sum += (o - 1)->i; /* { dg-line testA } */
/* Concrete inner struct, has no container. */
o = container_of (&test2);
sum += o->i; /* { dg-line testB } */
return sum;
/* { dg-warning "underread" "warning" { target *-*-* } testA } */
/* { dg-message "" "note" { target *-*-* } testA } */
/* { dg-warning "underread" "warning" { target *-*-* } testB } */
/* { dg-message "" "note" { target *-*-* } testB } */
}