https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116605
Bug ID: 116605 Summary: __builtin_object_size and __builtin_dynamic_object_size in mode 1 fall back to mode 0 for rows of multidimensional arrays Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: gustavo at embeddedor dot com Target Milestone: --- __builtin_object_size() and __builtin_dynamic_object_size() in mode 1 fail to correctly determine the size of multidimensional arrays when the addresses of their rows are passed as arguments. In this scenario, the built-in functions fall back to mode 0. See the example code below[1]. #include <stdio.h> #define expect(p, _v) do { \ size_t v = _v; \ if (p == v) \ printf("ok: %s == %zu\n", #p, p); \ else \ printf("WAT: %s == %zu (expected %zu)\n", #p, p, v); \ } while (0); const char array[][10] = { [0] = "0123456789", [1] = "0123456789", [2] = "0123456789", [3] = "0123456789", [4] = "0123456789" }; int main(void) { /* the whole object: array */ printf("\nWhole object: sizeof(array) = %zu\n", sizeof(array)); expect(sizeof(array), 50); expect(__builtin_object_size(array, 1), 50); expect(__builtin_object_size(array, 0), 50); expect(__builtin_dynamic_object_size(array, 1), 50); expect(__builtin_dynamic_object_size(array, 0), 50); /* first row: *array */ printf("\nFirst row: sizeof(*array) = %zu\n", sizeof(*array)); expect(sizeof(*array), 10); expect(__builtin_object_size(*array, 1), 10); expect(__builtin_object_size(*array, 0), 50); expect(__builtin_dynamic_object_size(*array, 1), 10); expect(__builtin_dynamic_object_size(*array, 0), 50); /* second row: array[1] */ printf("\nSecond row: sizeof(array[1]) = %zu\n", sizeof(array[1])); expect(sizeof(array[1]), 10); expect(__builtin_object_size(array[1], 1), 10); expect(__builtin_object_size(array[1], 0), 40); expect(__builtin_dynamic_object_size(array[1], 1), 10); expect(__builtin_dynamic_object_size(array[1], 0), 40); return 0; } Clang (trunk) correctly resolves the sizes: Whole object: sizeof(array) = 50 ok: sizeof(array) == 50 ok: __builtin_object_size(array, 1) == 50 ok: __builtin_object_size(array, 0) == 50 ok: __builtin_dynamic_object_size(array, 1) == 50 ok: __builtin_dynamic_object_size(array, 0) == 50 First row: sizeof(*array) = 10 ok: sizeof(*array) == 10 ok: __builtin_object_size(*array, 1) == 10 ok: __builtin_object_size(*array, 0) == 50 ok: __builtin_dynamic_object_size(*array, 1) == 10 ok: __builtin_dynamic_object_size(*array, 0) == 50 Second row: sizeof(array[1]) = 10 ok: sizeof(array[1]) == 10 ok: __builtin_object_size(array[1], 1) == 10 ok: __builtin_object_size(array[1], 0) == 40 ok: __builtin_dynamic_object_size(array[1], 1) == 10 ok: __builtin_dynamic_object_size(array[1], 0) == 40 However, GCC (trunk) produces some incorrect results: Whole object: sizeof(array) = 50 ok: sizeof(array) == 50 ok: __builtin_object_size(array, 1) == 50 ok: __builtin_object_size(array, 0) == 50 ok: __builtin_dynamic_object_size(array, 1) == 50 ok: __builtin_dynamic_object_size(array, 0) == 50 First row: sizeof(*array) = 10 ok: sizeof(*array) == 10 WAT: __builtin_object_size(*array, 1) == 50 (expected 10) ok: __builtin_object_size(*array, 0) == 50 WAT: __builtin_dynamic_object_size(*array, 1) == 50 (expected 10) ok: __builtin_dynamic_object_size(*array, 0) == 50 Second row: sizeof(array[1]) = 10 ok: sizeof(array[1]) == 10 WAT: __builtin_object_size(array[1], 1) == 40 (expected 10) ok: __builtin_object_size(array[1], 0) == 40 WAT: __builtin_dynamic_object_size(array[1], 1) == 40 (expected 10) ok: __builtin_dynamic_object_size(array[1], 0) == 40 [1] https://godbolt.org/z/afWMKKoGo