Cydox wrote:

> AIUI, GCC considers this to be a bug in the face of `counted_by`. The reason 
> GCC returns "unknown" (`SIZE_MAX`) in the case of a pointer like that is 
> because (prior to `counted_by`) if the pointer wasn't to local storage, it 
> could no know if it was a singleton or not. i.e. it may be pointing into a 
> larger array of objects, so it cannot know the size. (This is most clear for 
> `char *` variables, for example.)
> This shows how GCC will adjust the `__bdos` when it is certain of the object 
> being a singleton, but it still missing the "counted_by requires a singleton" 
> logic. (See also `-Wflexible-array-member-not-at-end` in GCC). It also shows 
> that Clang's `__bdos` can be lied to.

You can also lie to gcc if you do `__bdos(p->array, 1)`:
https://godbolt.org/z/ME5bd7nr9
```C
// gcc and clang: 40
void local_storage_lies_fam(void)
{
    struct foo local = { .counter = 10 };
    struct foo *p = &local;

    emit_length(__builtin_dynamic_object_size(p->array, 1));
}
```

I did some more digging and at least the comments in the tests from gcc seem to 
confirm the difference in behavior between lookind at `__bdos` of the FAM vs 
the whole struct:

Whole struct only uses the size from a known call to malloc, while bdos on FAM 
uses the counted_by attribute.

https://github.com/gcc-mirror/gcc/blob/3f10a2421c2b9c41e7c1b1c0d956743709f5d0be/gcc/testsuite/gcc.dg/flex-array-counted-by-4.c#L113-L141:

```C
  p->foo = index + SIZE_BUMP;

  /* When checking the observed access p->array, we have info on both
    observered allocation and observed access,
    A.1 from observed allocation:
        allocated_size - offsetof (struct annotated, array[0])
    A.2 from the counted-by attribute:
        p->foo * sizeof (char)

    We always use the latest value that is hold by the counted-by field.
   */

  EXPECT(__builtin_dynamic_object_size(p->array, 0),
         (p->foo) * sizeof(char));

  EXPECT(__builtin_dynamic_object_size(p->array, 1),
         (p->foo) * sizeof(char));

  EXPECT(__builtin_dynamic_object_size(p->array, 2),
         (p->foo) * sizeof(char));

  EXPECT(__builtin_dynamic_object_size(p->array, 3),
         (p->foo) * sizeof(char));

  /* When checking the pointer p, we only have info on the observed
    allocation. So, the object size info can only been obtained from
    the call to malloc.  */
  EXPECT(__builtin_dynamic_object_size(p, 0), allocated_size);
  EXPECT(__builtin_dynamic_object_size(p, 1), allocated_size);
  EXPECT(__builtin_dynamic_object_size(p, 2), allocated_size);
  EXPECT(__builtin_dynamic_object_size(p, 3), allocated_size);
```

clang on the other hand will always do it's counted_by calculation if the 
attribute is there. Both for bdos on the FAM, as well as bdos on the whole 
struct.

https://github.com/llvm/llvm-project/pull/111015
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to