On Wed, 10 Aug 2022, Qing Zhao wrote: > Hi, > > As mentioned in the bug report, I reopened this bug since the previous patch: > > commit r13-1875-gff26f0ba68fe6e870f315d0601b596f889b89680 > Author: Richard Biener <rguent...@suse.de> > Date: Thu Jul 28 10:07:32 2022 +0200 > > middle-end/106457 - improve array_at_struct_end_p for array objects > Array references to array objects are never at struct end. > > > Didn’t resolve this bug. > > This is a new patch, and my current work on -fstrict-flex-array depends on > this patch. > > Please take a look at the patch and let me know whether it’s good for > committing. > > Thanks. > > Qing. > > > ====================================== > > [PATCH] middle-end/106457 - improve array_at_struct_end_p for array > objects (PR106457) > > Array references are not handled correctly by current array_at_struct_end_p, > for the following array references: > > Example 1: (from gcc/testsuite/gcc.dg/torture/pr50067-[1|2].c): > > short a[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, > 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; > ... = (*((char(*)[32])&a[0]))[i+8]; // this array reference
For this one we have (gdb) p debug_generic_expr (ref_to_array) MEM[(char[32] *)&a] at the 12782 if (DECL_P (ref_to_array)) check. The array referenced (char[32]) isn't the decl (which is short[32]), so the referenced array (char[32]) _is_ at struct end since accessing index 48 is OK - it won't exceed the decl boundary. In fact that -Waggressive-loop-optimizations triggers with your patch shows it is wrong in this case - the code is perfectly OK, no out-of-bound access occurs. When this warning triggers it hints at the code being miscompiled (we usually elide the exit test). > Example 2: (from gcc/testsuite/gcc.target/aarch64/vadd_reduc-2.c): > > int test (uint8_t *p, uint32_t t[1][1], int n) { > for (int i = 0; i < 4; i++, p++) > t[i][0] = ...; // this array reference > ... > } The parameter declaration uint32_t t[1][1] doesn't guarantee anything - it's just a pointer. So we cannot reasonably constrain accesses to sizeof(uint32_t). That means array_at_struct_end_p has to return true. > Example 3: (from gcc/testsuite/g++.dg/debug/debug5.C): > > int a = 1; > int b = 1; > int e[a][b]; > e[0][0] = 0; // this array reference That might be the only case we'd be allowed to say false. I see a single call with MEM[(int[0:D.1989][0:D.1986] *)&e.4][0]{lb: 0 sz: 4} that is, the caller has stripped the outermost [0] already. The issue here is unfortunate lowering of the alloca with constant size we originally have here. The array typed decl has type int[1] but we access it with type int[0:D.1989][0:D.1986]. We'd now have to prove that D.1989 and D.1986 are '1' (and not less). That doesn't look possible in general. Not sure if it is worth the trobble here. Eventually array_at_struct_end_p isn't the correct vehicle for diagnostics if you desparately need to avoid 'true' for the above cases. Note for the first case it's more about treating pointer to array with bounds in a stricter way than we do at the moment, not so much about arrays at struct end. But array_at_struct_end_p is used to query whether we have to assume there's storage beyond the declared bound of an array that is "valid" to access (and it's valid from the middle-end point of view in this case). Richard. > All the above array references are identified as TRUE by the current > array_at_struct_end_p, therefore treated as flexible array members. > Obviously, they are just simple array references, not an array refs > to the last field of a struture. The current array_at_struct_end_p handles > such array references incorrectly. > > In order to handle array references correctly, we could recursively check > its first operand if it's a MEM_REF or COMPONENT_REF and stop as FALSE > when otherwise. This resolved all the issues for ARRAY_REF. > > bootstrapped and regression tested on both X86 and Aarch64. > Multiple testing cases behave differently due to array_at_struct_end_p now > behave correctly (return FALSE now, then they are not flexible array member > anymore). Adjust these testing cases. > > There is one regression for gcc/target/aarch64/vadd_reduc-2.c is left > unresolved since the loop transformation is changed due to the changed > behavior > of array_at_struct_end_p, simple adjustment of the testing case doesnt work. > I will file a bug to record this regression. > > gcc/ChangeLog: > > PR middle-end/106457 > * tree.cc (array_at_struct_end_p): Handle array objects recursively > through its first operand. > > gcc/testsuite/ChangeLog: > > PR middle-end/106457 > * gcc.dg/torture/pr50067-1.c: Add -Wno-aggressive-loop-optimizations > to suppress warnings. > * gcc.dg/torture/pr50067-2.c: Likewise. > * gcc.target/aarch64/vadd_reduc-2.c: Likewise. > * gcc.target/i386/pr104059.c: Likewise. > > > The complete patch is at: > > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman; HRB 36809 (AG Nuernberg)