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