Hi, This is the 8th version of the patch set to extend "counted_by" attribute to pointer fields of structures, which fixes PR120929:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120929 The 8th version of the patch has the following difference compared to the 7th version: 1. Add the fix for PR120929 in gcc/tree-object-size.cc, and testing case for PR120929 gcc.dg/pr120929.c (in Patch 2); based on Sid's patch for P120929. https://gcc.gnu.org/pipermail/gcc-patches/2025-July/688588.html 2. Add one more testing case gcc.dg/pointer-counted-by-8.c to check the code generation of pointers with counted_by attribute (in Patch 1); 3. Handle error_mark_node returned by build_counted_by_ref. Impacted routines include (in Patch 1): * c-parser.cc (c_parser_postfix_expression): Handle returned error_mark_node from handle_counted_by_for_component_ref. * c-typeck.cc (build_counted_by_ref): Return error_mark_node when issue error. (handle_counted_by_for_component_ref): Handle returned error_mark_node from build_counted_by_ref. (build_component_ref): Handle returned error_mark_node from handle_counted_by_for_component_ref. The whole patch set has been bootstrapped and regression tested on both aarch64 and x86. Okay for trunk? Thanks. Qing ============================= The 7th version of the patch has been committed into trunk, but triggered PR120929. I reverted the patches from trunk due to PR120929. In order to fix PR120929, we agreed on the following solution: Instead of passing the ADDRESS of the original pointer as the first argument to the call to .ACCESS_WITH_SIZE, we should pass the VALUE of the original pointer. The same for the returned value from the call to .ACCESS_WITH_SIZE. However, this design of the .ACCESS_WITH_SIZE for pointers with counted_by turns out to have an fundamental issue as explained below. For a pointer field with counted_by attribute: struct S { int n; int *p __attribute__((counted_by(n))); } *f; f->p = malloc (size); there are two approaches to generate the call to .ACCESS_WITH_SIZE for f->p. A. Pass the ADDRESS of the original pointer &(f->p) as the first argument, and also return the ADDRESS of the original pointer: *.ACCESS_WITH_SIZE (&f->p, &f->n,...) B. Pass the VALUE of the original pointer f->p as the first argument, and also return the original pointer: .ACCESS_WITH_SIZE (f->p, &f->n,...) The approach A was used in the previous committed (and reverted) patch; The approach B was suggested and agreed to fix PR120929 based on our previous discussion on PR120929. After study, the approach B is confirmed to bring undefined behavior into the application. f->p = malloc (size); ***** With the approach B: the IL for the above is: tmp1 = f->p; tmp2 = &f->n; tmp3 = .ACCESS_WITH_SIZE (tmp1, tmp2, ...); tmp4 = malloc (size); tmp3 = tmp4; In the above, in order to generate a call to .ACCESS_WITH_SIZE for the pointer reference f->p, the new GIMPLE tmp1 = f->p is necessary to pass the value of the pointer f->p to the call to .ACCESS_WITH_SIZE. However, this new GIMPLE is the one that brings UB into the application since the value of f->p is not initialized yet when it is assigned to "tmp1". the above IL will be expanded to the following when .ACCESS_WITH_SIZE is expanded to its first argument: tmp1 = f->p; tmp2 = &f->n; tmp3 = tmp1; tmp4 = malloc (size); tmp3 = tmp4; the final optimized IL will be: tmp3 = f->p; tmp3 = malloc (size);; As a result, the f->p will NOT be set correctly to the pointer returned by malloc (size). ***** With the Approach A, the IL is: tmp1 = &f->p; tmp2 = &f->n; tmp3 = .ACCESS_WITH_SIZE (tmp1, tmp2, ...); tmp4 = malloc (size); *tmp3 = tmp4; After .ACCESS_WITH_SIZE is expanded to its first argument: tmp1 = &f->p; tmp2 = &f->n; tmp3 = tmp1; tmp4 = malloc (size); *tmp3 = tmp4; The final optimized IL will be: *(&f->p) = malloc (size); Which is the correct IL for the original source code. Based on the above, We should take the Approach A for the pointers with counted_by attribute. i.e: A. Pass the ADDRESS of the original pointer &(f->p) as the first argument, and also return the ADDRESS of the original pointer: *.ACCESS_WITH_SIZE (&f->p, &f->n,...)